summaryrefslogtreecommitdiff
path: root/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp')
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp435
1 files changed, 296 insertions, 139 deletions
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 91e7f3353270..06908fecf984 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
@@ -23,7 +19,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RangeMap.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
@@ -41,12 +36,13 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -919,12 +915,10 @@ size_t ObjectFileMachO::GetModuleSpecifications(
spec.SetObjectOffset(file_offset);
spec.SetObjectSize(length);
- if (GetArchitecture(header, data, data_offset,
- spec.GetArchitecture())) {
- if (spec.GetArchitecture().IsValid()) {
- GetUUID(header, data, data_offset, spec.GetUUID());
- specs.Append(spec);
- }
+ spec.GetArchitecture() = GetArchitecture(header, data, data_offset);
+ if (spec.GetArchitecture().IsValid()) {
+ GetUUID(header, data, data_offset, spec.GetUUID());
+ specs.Append(spec);
}
}
}
@@ -962,6 +956,11 @@ const ConstString &ObjectFileMachO::GetSegmentNameLINKEDIT() {
return g_section_name_LINKEDIT;
}
+const ConstString &ObjectFileMachO::GetSegmentNameDWARF() {
+ static ConstString g_section_name("__DWARF");
+ return g_section_name;
+}
+
const ConstString &ObjectFileMachO::GetSectionNameEHFrame() {
static ConstString g_section_name_eh_frame("__eh_frame");
return g_section_name_eh_frame;
@@ -1102,9 +1101,7 @@ bool ObjectFileMachO::ParseHeader() {
if (can_parse) {
m_data.GetU32(&offset, &m_header.cputype, 6);
- ArchSpec mach_arch;
-
- if (GetArchitecture(mach_arch)) {
+ if (ArchSpec mach_arch = GetArchitecture()) {
// Check if the module has a required architecture
const ArchSpec &module_arch = module_sp->GetArchitecture();
if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
@@ -1191,21 +1188,28 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAbbrevDwo:
case eSectionTypeDWARFDebugAddr:
case eSectionTypeDWARFDebugAranges:
case eSectionTypeDWARFDebugCuIndex:
case eSectionTypeDWARFDebugFrame:
case eSectionTypeDWARFDebugInfo:
+ case eSectionTypeDWARFDebugInfoDwo:
case eSectionTypeDWARFDebugLine:
+ case eSectionTypeDWARFDebugLineStr:
case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocLists:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
@@ -1455,6 +1459,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
static ConstString g_sect_name_dwarf_debug_info("__debug_info");
static ConstString g_sect_name_dwarf_debug_line("__debug_line");
static ConstString g_sect_name_dwarf_debug_loc("__debug_loc");
+ static ConstString g_sect_name_dwarf_debug_loclists("__debug_loclists");
static ConstString g_sect_name_dwarf_debug_macinfo("__debug_macinfo");
static ConstString g_sect_name_dwarf_debug_names("__debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames("__debug_pubnames");
@@ -1484,6 +1489,8 @@ static lldb::SectionType GetSectionType(uint32_t flags,
return eSectionTypeDWARFDebugLine;
if (section_name == g_sect_name_dwarf_debug_loc)
return eSectionTypeDWARFDebugLoc;
+ if (section_name == g_sect_name_dwarf_debug_loclists)
+ return eSectionTypeDWARFDebugLocLists;
if (section_name == g_sect_name_dwarf_debug_macinfo)
return eSectionTypeDWARFDebugMacInfo;
if (section_name == g_sect_name_dwarf_debug_names)
@@ -1493,7 +1500,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
if (section_name == g_sect_name_dwarf_debug_pubtypes)
return eSectionTypeDWARFDebugPubTypes;
if (section_name == g_sect_name_dwarf_debug_ranges)
- return eSectionTypeDWARFDebugRanges;
+ return eSectionTypeDWARFDebugRanges;
if (section_name == g_sect_name_dwarf_debug_str)
return eSectionTypeDWARFDebugStr;
if (section_name == g_sect_name_dwarf_debug_types)
@@ -1668,7 +1675,7 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_,
} else if (unified_section_sp) {
if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
// Check to see if the module was read from memory?
- if (module_sp->GetObjectFile()->GetHeaderAddress().IsValid()) {
+ if (module_sp->GetObjectFile()->GetBaseAddress().IsValid()) {
// We have a module that is in memory and needs to have its file
// address adjusted. We need to do this because when we load a file
// from memory, its addresses will be slid already, yet the addresses
@@ -2177,7 +2184,7 @@ size_t ObjectFileMachO::ParseSymtab() {
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
const char *path = m_data.PeekCStr(name_offset);
if (path) {
- FileSpec file_spec(path, false);
+ FileSpec file_spec(path);
// Strip the path if there is @rpath, @executable, etc so we just use
// the basename
if (path[0] == '@')
@@ -2331,14 +2338,6 @@ size_t ObjectFileMachO::ParseSymtab() {
if (nlist_data_sp)
nlist_data.SetData(nlist_data_sp, 0,
nlist_data_sp->GetByteSize());
- // Load strings individually from memory when loading from memory
- // since shared cache string tables contain strings for all symbols
- // from all shared cached libraries DataBufferSP strtab_data_sp
- // (ReadMemory (process_sp, strtab_addr,
- // strtab_data_byte_size));
- // if (strtab_data_sp)
- // strtab_data.SetData (strtab_data_sp, 0,
- // strtab_data_sp->GetByteSize());
if (m_dysymtab.nindirectsyms != 0) {
const addr_t indirect_syms_addr = linkedit_load_addr +
m_dysymtab.indirectsymoff -
@@ -2350,8 +2349,25 @@ size_t ObjectFileMachO::ParseSymtab() {
indirect_symbol_index_data.SetData(
indirect_syms_data_sp, 0,
indirect_syms_data_sp->GetByteSize());
+ // If this binary is outside the shared cache,
+ // cache the string table.
+ // Binaries in the shared cache all share a giant string table, and
+ // we can't share the string tables across multiple ObjectFileMachO's,
+ // so we'd end up re-reading this mega-strtab for every binary
+ // in the shared cache - it would be a big perf problem.
+ // For binaries outside the shared cache, it's faster to read the
+ // entire strtab at once instead of piece-by-piece as we process
+ // the nlist records.
+ if ((m_header.flags & 0x80000000u) == 0) {
+ DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr,
+ strtab_data_byte_size));
+ if (strtab_data_sp) {
+ strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+ }
+ }
}
- } else if (memory_module_load_level >=
+ }
+ if (memory_module_load_level >=
eMemoryModuleLoadLevelPartial) {
if (function_starts_load_command.cmd) {
const addr_t func_start_addr =
@@ -2621,7 +2637,7 @@ size_t ObjectFileMachO::ParseSymtab() {
// shared cache UUID in the development or non-development shared caches
// on disk.
if (process_shared_cache_uuid.IsValid()) {
- if (dsc_development_filespec.Exists()) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
UUID dsc_development_uuid = GetSharedCacheUUID(
dsc_development_filespec, byte_order, addr_byte_size);
if (dsc_development_uuid.IsValid() &&
@@ -2630,7 +2646,8 @@ size_t ObjectFileMachO::ParseSymtab() {
dsc_uuid = dsc_development_uuid;
}
}
- if (!dsc_uuid.IsValid() && dsc_nondevelopment_filespec.Exists()) {
+ if (!dsc_uuid.IsValid() &&
+ FileSystem::Instance().Exists(dsc_nondevelopment_filespec)) {
UUID dsc_nondevelopment_uuid = GetSharedCacheUUID(
dsc_nondevelopment_filespec, byte_order, addr_byte_size);
if (dsc_nondevelopment_uuid.IsValid() &&
@@ -2643,8 +2660,8 @@ size_t ObjectFileMachO::ParseSymtab() {
// Failing a UUID match, prefer the development dyld_shared cache if both
// are present.
- if (!dsc_filespec.Exists()) {
- if (dsc_development_filespec.Exists()) {
+ if (!FileSystem::Instance().Exists(dsc_filespec)) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
dsc_filespec = dsc_development_filespec;
} else {
dsc_filespec = dsc_nondevelopment_filespec;
@@ -3052,11 +3069,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// file so you end up with a path that looks
// like "/tmp/src//tmp/src/"
FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
+ if (!FileSystem::Instance().Exists(so_dir)) {
so_dir.SetFile(
&full_so_path[double_slash_pos + 1],
false);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0,
double_slash_pos + 1);
@@ -4001,11 +4018,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// string in the DW_AT_comp_dir, and the second is the
// directory for the source file so you end up with a path
// that looks like "/tmp/src//tmp/src/"
- FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
- so_dir.SetFile(&full_so_path[double_slash_pos + 1], false,
+ FileSpec so_dir(so_path);
+ if (!FileSystem::Instance().Exists(so_dir)) {
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1],
FileSpec::Style::native);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0, double_slash_pos + 1);
}
@@ -4453,7 +4470,7 @@ size_t ObjectFileMachO::ParseSymtab() {
symbol_value -= section_file_addr;
}
- if (is_debug == false) {
+ if (!is_debug) {
if (type == eSymbolTypeCode) {
// See if we can find a N_FUN entry for any code symbols. If we
// do find a match, and the name matches, then we can merge the
@@ -4600,7 +4617,7 @@ size_t ObjectFileMachO::ParseSymtab() {
if (function_starts_count > 0) {
uint32_t num_synthetic_function_symbols = 0;
for (i = 0; i < function_starts_count; ++i) {
- if (function_starts.GetEntryRef(i).data == false)
+ if (!function_starts.GetEntryRef(i).data)
++num_synthetic_function_symbols;
}
@@ -4612,7 +4629,7 @@ size_t ObjectFileMachO::ParseSymtab() {
for (i = 0; i < function_starts_count; ++i) {
const FunctionStarts::Entry *func_start_entry =
function_starts.GetEntryAtIndex(i);
- if (func_start_entry->data == false) {
+ if (!func_start_entry->data) {
addr_t symbol_file_addr = func_start_entry->addr;
uint32_t symbol_flags = 0;
if (is_arm) {
@@ -4817,8 +4834,7 @@ void ObjectFileMachO::Dump(Stream *s) {
else
s->PutCString("ObjectFileMachO32");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', triple = " << header_arch.GetTriple().getTriple() << "\n";
@@ -4869,25 +4885,83 @@ bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
return false;
}
-static const char *GetOSName(uint32_t cmd) {
+static llvm::StringRef GetOSName(uint32_t cmd) {
switch (cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
- return "ios";
+ return llvm::Triple::getOSTypeName(llvm::Triple::IOS);
case llvm::MachO::LC_VERSION_MIN_MACOSX:
- return "macosx";
+ return llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
case llvm::MachO::LC_VERSION_MIN_TVOS:
- return "tvos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
case llvm::MachO::LC_VERSION_MIN_WATCHOS:
- return "watchos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
default:
llvm_unreachable("unexpected LC_VERSION load command");
}
}
-bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
- const lldb_private::DataExtractor &data,
- lldb::offset_t lc_offset,
- ArchSpec &arch) {
+namespace {
+ struct OSEnv {
+ llvm::StringRef os_type;
+ llvm::StringRef environment;
+ OSEnv(uint32_t cmd) {
+ switch (cmd) {
+ case PLATFORM_MACOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
+ return;
+ case PLATFORM_IOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ return;
+ case PLATFORM_TVOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ return;
+ case PLATFORM_WATCHOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ return;
+// NEED_BRIDGEOS_TRIPLE case PLATFORM_BRIDGEOS:
+// NEED_BRIDGEOS_TRIPLE os_type = llvm::Triple::getOSTypeName(llvm::Triple::BridgeOS);
+// NEED_BRIDGEOS_TRIPLE return;
+#if defined (PLATFORM_IOSSIMULATOR) && defined (PLATFORM_TVOSSIMULATOR) && defined (PLATFORM_WATCHOSSIMULATOR)
+ case PLATFORM_IOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_TVOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_WATCHOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+#endif
+ default: {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS |
+ LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("unsupported platform in LC_BUILD_VERSION");
+ }
+ }
+ }
+ };
+
+ struct MinOS {
+ uint32_t major_version, minor_version, patch_version;
+ MinOS(uint32_t version)
+ : major_version(version >> 16),
+ minor_version((version >> 8) & 0xffu),
+ patch_version(version & 0xffu) {}
+ };
+} // namespace
+
+ArchSpec
+ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset) {
+ ArchSpec arch;
arch.SetArchitecture(eArchTypeMachO, header.cputype, header.cpusubtype);
if (arch.IsValid()) {
@@ -4912,39 +4986,37 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
triple.setVendor(llvm::Triple::UnknownVendor);
triple.setVendorName(llvm::StringRef());
}
- return true;
+ return arch;
} else {
struct load_command load_cmd;
+ llvm::SmallString<16> os_name;
+ llvm::raw_svector_ostream os(os_name);
+ // See if there is an LC_VERSION_MIN_* load command that can give
+ // us the OS type.
lldb::offset_t offset = lc_offset;
for (uint32_t i = 0; i < header.ncmds; ++i) {
const lldb::offset_t cmd_offset = offset;
if (data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
- uint32_t major, minor, patch;
struct version_min_command version_min;
-
- llvm::SmallString<16> os_name;
- llvm::raw_svector_ostream os(os_name);
-
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
case llvm::MachO::LC_VERSION_MIN_MACOSX:
case llvm::MachO::LC_VERSION_MIN_TVOS:
- case llvm::MachO::LC_VERSION_MIN_WATCHOS:
+ case llvm::MachO::LC_VERSION_MIN_WATCHOS: {
if (load_cmd.cmdsize != sizeof(version_min))
break;
- data.ExtractBytes(cmd_offset,
- sizeof(version_min), data.GetByteOrder(),
- &version_min);
- major = version_min.version >> 16;
- minor = (version_min.version >> 8) & 0xffu;
- patch = version_min.version & 0xffu;
- os << GetOSName(load_cmd.cmd) << major << '.' << minor << '.'
- << patch;
+ if (data.ExtractBytes(cmd_offset, sizeof(version_min),
+ data.GetByteOrder(), &version_min) == 0)
+ break;
+ MinOS min_os(version_min.version);
+ os << GetOSName(load_cmd.cmd) << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
triple.setOSName(os.str());
- return true;
+ return arch;
+ }
default:
break;
}
@@ -4952,6 +5024,39 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
offset = cmd_offset + load_cmd.cmdsize;
}
+ // See if there is an LC_BUILD_VERSION load command that can give
+ // us the OS type.
+
+ offset = lc_offset;
+ for (uint32_t i = 0; i < header.ncmds; ++i) {
+ const lldb::offset_t cmd_offset = offset;
+ if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+ do {
+ if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ struct build_version_command build_version;
+ if (load_cmd.cmdsize < sizeof(build_version)) {
+ // Malformed load command.
+ break;
+ }
+ if (data.ExtractBytes(cmd_offset, sizeof(build_version),
+ data.GetByteOrder(), &build_version) == 0)
+ break;
+ MinOS min_os(build_version.minos);
+ OSEnv os_env(build_version.platform);
+ if (os_env.os_type.empty())
+ break;
+ os << os_env.os_type << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
+ triple.setOSName(os.str());
+ if (!os_env.environment.empty())
+ triple.setEnvironmentName(os_env.environment);
+ return arch;
+ }
+ } while (0);
+ offset = cmd_offset + load_cmd.cmdsize;
+ }
+
if (header.filetype != MH_KEXT_BUNDLE) {
// We didn't find a LC_VERSION_MIN load command and this isn't a KEXT
// so lets not say our Vendor is Apple, leave it as an unspecified
@@ -4961,7 +5066,7 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
}
}
}
- return arch.IsValid();
+ return arch;
}
bool ObjectFileMachO::GetUUID(lldb_private::UUID *uuid) {
@@ -4984,9 +5089,6 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
std::vector<std::string> rpath_paths;
std::vector<std::string> rpath_relative_paths;
std::vector<std::string> at_exec_relative_paths;
- const bool resolve_path = false; // Don't resolve the dependent file paths
- // since they may not reside on this
- // system
uint32_t i;
for (i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5015,7 +5117,7 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
at_exec_relative_paths.push_back(path
+ strlen("@executable_path"));
} else {
- FileSpec file_spec(path, resolve_path);
+ FileSpec file_spec(path);
if (files.AppendIfUnique(file_spec))
count++;
}
@@ -5030,8 +5132,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
}
FileSpec this_file_spec(m_file);
- this_file_spec.ResolvePath();
-
+ FileSystem::Instance().Resolve(this_file_spec);
+
if (!rpath_paths.empty()) {
// Fixup all LC_RPATH values to be absolute paths
std::string loader_path("@loader_path");
@@ -5052,8 +5154,10 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
path += rpath_relative_path;
// It is OK to resolve this path because we must find a file on disk
// for us to accept it anyway if it is rpath relative.
- FileSpec file_spec(path, true);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec)) {
count++;
break;
}
@@ -5070,7 +5174,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
FileSpec file_spec =
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec))
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec))
count++;
}
}
@@ -5235,7 +5340,7 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
return m_entry_point_address;
}
-lldb_private::Address ObjectFileMachO::GetHeaderAddress() {
+lldb_private::Address ObjectFileMachO::GetBaseAddress() {
lldb_private::Address header_addr;
SectionList *section_list = GetSectionList();
if (section_list) {
@@ -5583,14 +5688,16 @@ llvm::VersionTuple ObjectFileMachO::GetVersion() {
return llvm::VersionTuple();
}
-bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFileMachO::GetArchitecture() {
ModuleSP module_sp(GetModule());
+ ArchSpec arch;
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
return GetArchitecture(m_header, m_data,
- MachHeaderSizeFromMagic(m_header.magic), arch);
+ MachHeaderSizeFromMagic(m_header.magic));
}
- return false;
+ return arch;
}
void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) {
@@ -5716,8 +5823,30 @@ llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() {
m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
break;
}
+ }
+ } else if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
+ // /* ntools * sizeof(struct build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t ntools; /* number of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
+ break;
}
}
+
offset = load_cmd_offset + lc.cmdsize;
}
@@ -5735,7 +5864,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
if (m_sdk_versions.empty()) {
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
bool success = false;
- for (uint32_t i = 0; success == false && i < m_header.ncmds; ++i) {
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
@@ -5764,7 +5893,46 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
offset = load_cmd_offset + lc.cmdsize;
}
- if (success == false) {
+ if (!success) {
+ offset = MachHeaderSizeFromMagic(m_header.magic);
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
+ const lldb::offset_t load_cmd_offset = offset;
+
+ version_min_command lc;
+ if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
+ break;
+ if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct
+ // build_version_command) plus */
+ // /* ntools * sizeof(struct
+ // build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles
+ // xxxx.yy.zz */ uint32_t sdk; /* X.Y.Z is encoded
+ // in nibbles xxxx.yy.zz */ uint32_t ntools; /* number
+ // of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_sdk_versions.push_back(xxxx);
+ m_sdk_versions.push_back(yy);
+ m_sdk_versions.push_back(zz);
+ success = true;
+ }
+ }
+ offset = load_cmd_offset + lc.cmdsize;
+ }
+ }
+
+ if (!success) {
// Push an invalid value so we don't try to find
// the version # again on the next call to this
// method.
@@ -5814,52 +5982,52 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
// the mach-o file which can be subtracted from the vmaddr of the other
// segments found in memory and added to the load address
ModuleSP module_sp = GetModule();
- if (module_sp) {
- SectionList *section_list = GetSectionList();
- if (section_list) {
- lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS;
- const size_t num_sections = section_list->GetSize();
-
- for (size_t sect_idx = 0; sect_idx < num_sections &&
- mach_base_file_addr == LLDB_INVALID_ADDRESS;
- ++sect_idx) {
- Section *section = section_list->GetSectionAtIndex(sect_idx).get();
- if (section && section->GetFileSize() > 0 &&
- section->GetFileOffset() == 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- return section;
- }
- }
- }
+ if (!module_sp)
+ return nullptr;
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return nullptr;
+ const size_t num_sections = section_list->GetSize();
+ for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+ Section *section = section_list->GetSectionAtIndex(sect_idx).get();
+ if (section->GetFileOffset() == 0 && SectionIsLoadable(section))
+ return section;
}
return nullptr;
}
+bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
+ if (!section)
+ return false;
+ const bool is_dsym = (m_header.filetype == MH_DSYM);
+ if (section->GetFileSize() == 0 && !is_dsym)
+ return false;
+ if (section->IsThreadSpecific())
+ return false;
+ if (GetModule().get() != section->GetModule().get())
+ return false;
+ // Be careful with __LINKEDIT and __DWARF segments
+ if (section->GetName() == GetSegmentNameLINKEDIT() ||
+ section->GetName() == GetSegmentNameDWARF()) {
+ // Only map __LINKEDIT and __DWARF if we have an in memory image and
+ // this isn't a kernel binary like a kext or mach_kernel.
+ const bool is_memory_image = (bool)m_process_wp.lock();
+ const Strata strata = GetStrata();
+ if (is_memory_image == false || strata == eStrataKernel)
+ return false;
+ }
+ return true;
+}
+
lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(
- lldb::addr_t mach_header_load_address, const Section *mach_header_section,
+ lldb::addr_t header_load_address, const Section *header_section,
const Section *section) {
ModuleSP module_sp = GetModule();
- if (module_sp && mach_header_section && section &&
- mach_header_load_address != LLDB_INVALID_ADDRESS) {
- lldb::addr_t mach_header_file_addr = mach_header_section->GetFileAddress();
- if (mach_header_file_addr != LLDB_INVALID_ADDRESS) {
- if (section && section->GetFileSize() > 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this isn't a
- // kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- return LLDB_INVALID_ADDRESS;
- }
- return section->GetFileAddress() - mach_header_file_addr +
- mach_header_load_address;
- }
- }
+ if (module_sp && header_section && section &&
+ header_load_address != LLDB_INVALID_ADDRESS) {
+ lldb::addr_t file_addr = header_section->GetFileAddress();
+ if (file_addr != LLDB_INVALID_ADDRESS && SectionIsLoadable(section))
+ return section->GetFileAddress() - file_addr + header_load_address;
}
return LLDB_INVALID_ADDRESS;
}
@@ -5879,22 +6047,10 @@ bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the
// sections that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
- if (section_sp && section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false &&
- module_sp.get() == section_sp->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section_sp->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this
- // isn't a kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- continue;
- }
+ if (SectionIsLoadable(section_sp.get()))
if (target.GetSectionLoadList().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress() + value))
++num_loaded_sections;
- }
}
} else {
// "value" is the new base address of the mach_header, adjust each
@@ -5933,6 +6089,7 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
target_triple.getOS() == llvm::Triple::IOS ||
target_triple.getOS() == llvm::Triple::WatchOS ||
target_triple.getOS() == llvm::Triple::TvOS)) {
+ // NEED_BRIDGEOS_TRIPLE target_triple.getOS() == llvm::Triple::BridgeOS)) {
bool make_core = false;
switch (target_arch.GetMachine()) {
case llvm::Triple::aarch64:
@@ -6161,10 +6318,10 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
File core_file;
std::string core_file_path(outfile.GetPath());
- error = core_file.Open(core_file_path.c_str(),
- File::eOpenOptionWrite |
- File::eOpenOptionTruncate |
- File::eOpenOptionCanCreate);
+ error = FileSystem::Instance().Open(core_file, outfile,
+ File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate);
if (error.Success()) {
// Read 1 page at a time
uint8_t bytes[0x1000];