[Lldb-commits] [lldb] fda53ad - [lldb] Support Universal Mach-O binaries with a fat64 header
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Tue Mar 28 15:46:34 PDT 2023
Author: Jonas Devlieghere
Date: 2023-03-28T15:46:26-07:00
New Revision: fda53ad9374b60fc83f1a6065ae3e7985182a5d2
URL: https://github.com/llvm/llvm-project/commit/fda53ad9374b60fc83f1a6065ae3e7985182a5d2
DIFF: https://github.com/llvm/llvm-project/commit/fda53ad9374b60fc83f1a6065ae3e7985182a5d2.diff
LOG: [lldb] Support Universal Mach-O binaries with a fat64 header
Support universal Mach-O binaries with a fat64 header. After
4d683f7fa7d4, dsymutil can now generate such binaries when the offsets
would otherwise overflow the 32-bit offsets in the regular fat header.
rdar://107289570
Differential revision: https://reviews.llvm.org/D147012
Added:
lldb/test/API/macosx/universal64/Makefile
lldb/test/API/macosx/universal64/TestUniversal64.py
lldb/test/API/macosx/universal64/main.c
Modified:
lldb/packages/Python/lldbsuite/test/make/Makefile.rules
lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
Removed:
################################################################################
diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
index 4c225ed360be5..bfd249ccd43f2 100644
--- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -153,7 +153,7 @@ ARCHFLAG ?= -arch
#----------------------------------------------------------------------
ifeq "$(OS)" "Darwin"
DS := $(DSYMUTIL)
- DSFLAGS =
+ DSFLAGS := $(DSFLAGS_EXTRAS)
DSYM = $(EXE).dSYM
AR := $(CROSS_COMPILE)libtool
ARFLAGS := -static -o
diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
index 78e0a4b2f499f..9af9c0120dd7d 100644
--- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
+++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp
@@ -57,7 +57,8 @@ ObjectContainer *ObjectContainerUniversalMachO::CreateInstance(
bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) {
lldb::offset_t offset = 0;
uint32_t magic = data.GetU32(&offset);
- return magic == FAT_MAGIC || magic == FAT_CIGAM;
+ return magic == FAT_MAGIC || magic == FAT_CIGAM || magic == FAT_MAGIC_64 ||
+ magic == FAT_CIGAM_64;
}
ObjectContainerUniversalMachO::ObjectContainerUniversalMachO(
@@ -82,38 +83,51 @@ bool ObjectContainerUniversalMachO::ParseHeader() {
bool ObjectContainerUniversalMachO::ParseHeader(
lldb_private::DataExtractor &data, llvm::MachO::fat_header &header,
- std::vector<llvm::MachO::fat_arch> &fat_archs) {
- bool success = false;
+ std::vector<FatArch> &fat_archs) {
// Store the file offset for this universal file as we could have a universal
// .o file in a BSD archive, or be contained in another kind of object.
- // Universal mach-o files always have their headers in big endian.
lldb::offset_t offset = 0;
data.SetByteOrder(eByteOrderBig);
header.magic = data.GetU32(&offset);
fat_archs.clear();
- if (header.magic == FAT_MAGIC) {
-
- data.SetAddressByteSize(4);
+ // Universal mach-o files always have their headers in big endian.
+ if (header.magic == FAT_MAGIC || header.magic == FAT_MAGIC_64) {
+ const bool is_fat64 = header.magic == FAT_MAGIC_64;
+ data.SetAddressByteSize(is_fat64 ? 8 : 4);
header.nfat_arch = data.GetU32(&offset);
// Now we should have enough data for all of the fat headers, so lets index
// them so we know how many architectures that this universal binary
// contains.
- uint32_t arch_idx = 0;
- for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) {
+ for (uint32_t arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) {
if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) {
- fat_arch arch;
- if (data.GetU32(&offset, &arch, sizeof(fat_arch) / sizeof(uint32_t)))
- fat_archs.push_back(arch);
+ if (is_fat64) {
+ fat_arch_64 arch;
+ arch.cputype = data.GetU32(&offset);
+ arch.cpusubtype = data.GetU32(&offset);
+ arch.offset = data.GetU64(&offset);
+ arch.size = data.GetU64(&offset);
+ arch.align = data.GetU32(&offset);
+ arch.reserved = data.GetU32(&offset);
+ fat_archs.emplace_back(arch);
+ } else {
+ fat_arch arch;
+ arch.cputype = data.GetU32(&offset);
+ arch.cpusubtype = data.GetU32(&offset);
+ arch.offset = data.GetU32(&offset);
+ arch.size = data.GetU32(&offset);
+ arch.align = data.GetU32(&offset);
+ fat_archs.emplace_back(arch);
+ }
}
}
- success = true;
- } else {
- memset(&header, 0, sizeof(header));
+ return true;
}
- return success;
+
+ memset(&header, 0, sizeof(header));
+ return true;
}
size_t ObjectContainerUniversalMachO::GetNumArchitectures() const {
@@ -123,8 +137,8 @@ size_t ObjectContainerUniversalMachO::GetNumArchitectures() const {
bool ObjectContainerUniversalMachO::GetArchitectureAtIndex(
uint32_t idx, ArchSpec &arch) const {
if (idx < m_header.nfat_arch) {
- arch.SetArchitecture(eArchTypeMachO, m_fat_archs[idx].cputype,
- m_fat_archs[idx].cpusubtype);
+ arch.SetArchitecture(eArchTypeMachO, m_fat_archs[idx].GetCPUType(),
+ m_fat_archs[idx].GetCPUSubType());
return true;
}
return false;
@@ -166,8 +180,8 @@ ObjectContainerUniversalMachO::GetObjectFile(const FileSpec *file) {
DataBufferSP data_sp;
lldb::offset_t data_offset = 0;
return ObjectFile::FindPlugin(
- module_sp, file, m_offset + m_fat_archs[arch_idx].offset,
- m_fat_archs[arch_idx].size, data_sp, data_offset);
+ module_sp, file, m_offset + m_fat_archs[arch_idx].GetOffset(),
+ m_fat_archs[arch_idx].GetSize(), data_sp, data_offset);
}
}
return ObjectFileSP();
@@ -184,11 +198,12 @@ size_t ObjectContainerUniversalMachO::GetModuleSpecifications(
if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) {
llvm::MachO::fat_header header;
- std::vector<llvm::MachO::fat_arch> fat_archs;
+ std::vector<FatArch> fat_archs;
if (ParseHeader(data, header, fat_archs)) {
- for (const llvm::MachO::fat_arch &fat_arch : fat_archs) {
- const lldb::offset_t slice_file_offset = fat_arch.offset + file_offset;
- if (fat_arch.offset < file_size && file_size > slice_file_offset) {
+ for (const FatArch &fat_arch : fat_archs) {
+ const lldb::offset_t slice_file_offset =
+ fat_arch.GetOffset() + file_offset;
+ if (fat_arch.GetOffset() < file_size && file_size > slice_file_offset) {
ObjectFile::GetModuleSpecifications(
file, slice_file_offset, file_size - slice_file_offset, specs);
}
diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
index 4fbea936ac85c..20f1f051e07a0 100644
--- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
+++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
@@ -63,11 +63,46 @@ class ObjectContainerUniversalMachO : public lldb_private::ObjectContainer {
protected:
llvm::MachO::fat_header m_header;
- std::vector<llvm::MachO::fat_arch> m_fat_archs;
+
+ struct FatArch {
+ FatArch(llvm::MachO::fat_arch arch) : m_arch(arch), m_is_fat64(false) {}
+ FatArch(llvm::MachO::fat_arch_64 arch) : m_arch(arch), m_is_fat64(true) {}
+
+ uint32_t GetCPUType() const {
+ return m_is_fat64 ? m_arch.fat_arch_64.cputype : m_arch.fat_arch.cputype;
+ }
+
+ uint32_t GetCPUSubType() const {
+ return m_is_fat64 ? m_arch.fat_arch_64.cpusubtype
+ : m_arch.fat_arch.cpusubtype;
+ }
+
+ uint64_t GetOffset() const {
+ return m_is_fat64 ? m_arch.fat_arch_64.offset : m_arch.fat_arch.offset;
+ }
+
+ uint64_t GetSize() const {
+ return m_is_fat64 ? m_arch.fat_arch_64.size : m_arch.fat_arch.size;
+ }
+
+ uint32_t GetAlign() const {
+ return m_is_fat64 ? m_arch.fat_arch_64.align : m_arch.fat_arch.align;
+ }
+
+ private:
+ const union Arch {
+ Arch(llvm::MachO::fat_arch arch) : fat_arch(arch) {}
+ Arch(llvm::MachO::fat_arch_64 arch) : fat_arch_64(arch) {}
+ llvm::MachO::fat_arch fat_arch;
+ llvm::MachO::fat_arch_64 fat_arch_64;
+ } m_arch;
+ const bool m_is_fat64;
+ };
+ std::vector<FatArch> m_fat_archs;
static bool ParseHeader(lldb_private::DataExtractor &data,
llvm::MachO::fat_header &header,
- std::vector<llvm::MachO::fat_arch> &fat_archs);
+ std::vector<FatArch> &fat_archs);
};
#endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_UNIVERSAL_MACH_O_OBJECTCONTAINERUNIVERSALMACHO_H
diff --git a/lldb/test/API/macosx/universal64/Makefile b/lldb/test/API/macosx/universal64/Makefile
new file mode 100644
index 0000000000000..f763f3ae2f6c9
--- /dev/null
+++ b/lldb/test/API/macosx/universal64/Makefile
@@ -0,0 +1,24 @@
+EXE := fat.out
+
+ifdef FAT64_DSYM
+ DSFLAGS_EXTRAS=-fat64
+endif
+
+include Makefile.rules
+
+all: fat.out
+
+fat.out: fat.arm64.out fat.x86_64.out
+ lipo -fat64 -create -o $@ $^
+
+fat.x86_64.out: fat.x86_64.o
+ $(CC) -isysroot $(SDKROOT) -target x86_64-apple-macosx10.9 -o $@ $<
+
+fat.arm64.out: fat.arm64.o
+ $(CC) -isysroot $(SDKROOT) -target arm64-apple-macosx10.9 -o $@ $<
+
+fat.x86_64.o: main.c
+ $(CC) -isysroot $(SDKROOT) -g -O0 -target x86_64-apple-macosx11 -c -o $@ $<
+
+fat.arm64.o: main.c
+ $(CC) -isysroot $(SDKROOT) -g -O0 -target arm64-apple-macosx11 -c -o $@ $<
diff --git a/lldb/test/API/macosx/universal64/TestUniversal64.py b/lldb/test/API/macosx/universal64/TestUniversal64.py
new file mode 100644
index 0000000000000..0c4226fac5380
--- /dev/null
+++ b/lldb/test/API/macosx/universal64/TestUniversal64.py
@@ -0,0 +1,39 @@
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class Universal64TestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def do_test(self):
+ # Get the executable.
+ exe = self.getBuildArtifact("fat.out")
+
+ # Create a target.
+ self.target = self.dbg.CreateTarget(exe)
+
+ # Create a breakpoint on main.
+ main_bp = self.target.BreakpointCreateByName("main")
+ self.assertTrue(main_bp, VALID_BREAKPOINT)
+
+ # Make sure the binary and the dSYM are in the image list.
+ self.expect("image list ", patterns=['fat.out', 'fat.out.dSYM'])
+
+ # The dynamic loader doesn't support fat64 executables so we can't
+ # actually launch them here.
+
+ @skipUnlessDarwin
+ @skipIfDarwinEmbedded
+ def test_universal64_executable(self):
+ """Test fat64 universal executable"""
+ self.build(debug_info="dsym")
+ self.do_test()
+
+ @skipUnlessDarwin
+ @skipIfDarwinEmbedded
+ @skipIf(compiler="clang", compiler_version=['<', '7.0'])
+ def test_universal64_dsym(self):
+ """Test fat64 universal dSYM"""
+ self.build(debug_info="dsym", dictionary={'FAT64_DSYM': '1'})
+ self.do_test()
diff --git a/lldb/test/API/macosx/universal64/main.c b/lldb/test/API/macosx/universal64/main.c
new file mode 100644
index 0000000000000..5124e0afbfc19
--- /dev/null
+++ b/lldb/test/API/macosx/universal64/main.c
@@ -0,0 +1,5 @@
+#include <stdio.h>
+
+int foo() { return 0; }
+
+int main(int argc, char **argv) { return foo(); }
More information about the lldb-commits
mailing list