diff --git a/llvm/include/llvm/Object/ArchiveWriter.h b/llvm/include/llvm/Object/ArchiveWriter.h --- a/llvm/include/llvm/Object/ArchiveWriter.h +++ b/llvm/include/llvm/Object/ArchiveWriter.h @@ -31,6 +31,8 @@ static Expected getFile(StringRef FileName, bool Deterministic); + + bool isMacho() const; }; Expected computeArchiveRelativePath(StringRef From, StringRef To); diff --git a/llvm/lib/ObjCopy/Archive.cpp b/llvm/lib/ObjCopy/Archive.cpp --- a/llvm/lib/ObjCopy/Archive.cpp +++ b/llvm/lib/ObjCopy/Archive.cpp @@ -61,6 +61,10 @@ ArrayRef NewMembers, bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, bool Thin) { + if (Kind == object::Archive::K_BSD && !NewMembers.empty() && + NewMembers.front().isMacho()) + Kind = object::Archive::K_DARWIN; + if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind, Deterministic, Thin)) return createFileError(ArcName, std::move(E)); diff --git a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp --- a/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOObjcopy.cpp @@ -486,7 +486,8 @@ return NewArchiveMembersOrErr.takeError(); Expected> OutputBufferOrErr = writeArchiveToBuffer(*NewArchiveMembersOrErr, - (*ArOrErr)->hasSymbolTable(), (*ArOrErr)->kind(), + (*ArOrErr)->hasSymbolTable(), + object::Archive::K_DARWIN, Config.getCommonConfig().DeterministicArchives, (*ArOrErr)->isThin()); if (!OutputBufferOrErr) diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/Error.h" +#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" #include "llvm/Support/Alignment.h" @@ -113,6 +114,59 @@ return std::move(M); } +bool NewArchiveMember::isMacho() const { + auto Magic = identify_magic(Buf->getBuffer()); + switch (Magic) { + case file_magic::bitcode: { + LLVMContext Context; + if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile( + *Buf, file_magic::bitcode, &Context, false)) { + auto &IRObject = cast(**ObjOrErr); + return Triple(IRObject.getTargetTriple()).isOSDarwin(); + } else { + // Squelch the error in case this was not a SymbolicFile. + consumeError(ObjOrErr.takeError()); + } + + return false; + } + case file_magic::macho_bundle: + case file_magic::macho_core: + case file_magic::macho_dsym_companion: + case file_magic::macho_dynamic_linker: + case file_magic::macho_dynamically_linked_shared_lib: + case file_magic::macho_dynamically_linked_shared_lib_stub: + case file_magic::macho_executable: + case file_magic::macho_fixed_virtual_memory_shared_lib: + case file_magic::macho_kext_bundle: + case file_magic::macho_object: + case file_magic::macho_preload_executable: + case file_magic::macho_universal_binary: + return true; + case file_magic::archive: + case file_magic::coff_cl_gl_object: + case file_magic::coff_import_library: + case file_magic::coff_object: + case file_magic::cuda_fatbinary: + case file_magic::elf: + case file_magic::elf_core: + case file_magic::elf_executable: + case file_magic::elf_relocatable: + case file_magic::elf_shared_object: + case file_magic::goff_object: + case file_magic::minidump: + case file_magic::pdb: + case file_magic::pecoff_executable: + case file_magic::tapi_file: + case file_magic::unknown: + case file_magic::wasm_object: + case file_magic::windows_resource: + case file_magic::xcoff_object_32: + case file_magic::xcoff_object_64: + return false; + } +} + template static void printWithSpacePadding(raw_ostream &OS, T Data, unsigned Size) { uint64_t OldPos = OS.tell(); diff --git a/llvm/test/tools/llvm-ar/default-macho.test b/llvm/test/tools/llvm-ar/default-macho.test --- a/llvm/test/tools/llvm-ar/default-macho.test +++ b/llvm/test/tools/llvm-ar/default-macho.test @@ -7,3 +7,12 @@ Ensure that we generate a BSD style archive for MachO by default. ld64 expects that it will be in BSD format. +Make sure darwin specific alignment is preserved when updating the archive + +RUN: rm -rf %t; split-file %S/../llvm-objcopy/MachO/Inputs/unaligned_objects.yaml %t +RUN: yaml2obj %t/first-object.yaml > %t/first.o +RUN: yaml2obj %t/second-object.yaml > %t/second.o +RUN: llvm-ar --format=darwin crs %t/lib.a %t/first.o %t/second.o +RUN: cp %t/lib.a %t/originallib.a +RUN: llvm-ar crs %t/lib.a %t/second.o +RUN: cmp %t/lib.a %t/originallib.a diff --git a/llvm/test/tools/llvm-objcopy/MachO/Inputs/unaligned_objects.yaml b/llvm/test/tools/llvm-objcopy/MachO/Inputs/unaligned_objects.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/Inputs/unaligned_objects.yaml @@ -0,0 +1,279 @@ +#--- first-object.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x1 + ncmds: 4 + sizeofcmds: 208 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: '' + vmaddr: 0 + vmsize: 314 + fileoff: 240 + filesize: 314 + maxprot: 7 + initprot: 7 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 314 + offset: 0xF0 + align: 4 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E54839F7730431C05DC3480FBDCE4883F13F4885FF740A480FBDC74883F03FEB05B8400000004829C14889F048D3E089C94839C74883D9004989F349D3E34C29DF41B80100000049D3E04839F773054C89C05DC34D85DB78054C89C0EB2E49D1EB48FFC941B90100000049D3E131C04989FA4D29DA490F49C1490F49FA4C09C04D89C84839F70F82A900000049FFC84885C90F849700000049FFCB4C8D49FF4989CA4983E203742631F60F1F004801FF4889FA4C29DA4889D748C1FF3F4C21DF4801D748FFC64939F275E24829F14983F903725B660F1F8400000000004801FF4C29DF4889FA48C1FA3F4C21DA4801FA4801D24C29DA4889D648C1FE3F4C21DE4801D64801F64C29DE4889F248C1FA3F4C21DA4801F24801D24C29DA4889D748C1FF3F4C21DF4801D74883C1FC75AE4C21C74809F85DC3 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 554 + nsyms: 13 + stroff: 762 + strsize: 680 + - cmd: LC_VERSION_MIN_IPHONEOS + cmdsize: 16 + version: 458752 + sdk: 0 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 554 + datasize: 0 +LinkEditData: + NameList: + - n_strx: 572 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 539 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 672 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 528 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 398 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 297 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 130 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 1 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 214 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 672 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 314 + - n_strx: 672 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 314 + - n_strx: 672 + n_type: 0x64 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 528 + n_type: 0x1F + n_sect: 1 + n_desc: 0 + n_value: 0 + StringTable: + - '' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/int/specialized_div_rem/norm_shift.rs' + - '/rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/num/uint_macros.rs' + - '/rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/num/int_macros.rs' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/macros.rs' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/int/specialized_div_rem/binary_long.rs' + - ___udivdi3 + - compiler_builtins.f13b4771-cgu.1 + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/lib.rs/@/' + - '' + - '' + - '' + - '' + - '' + - '' + - '' +... + +#--- second-object.yaml +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x1000007 + cpusubtype: 0x3 + filetype: 0x1 + ncmds: 4 + sizeofcmds: 208 + flags: 0x2000 + reserved: 0x0 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: '' + vmaddr: 0 + vmsize: 94 + fileoff: 240 + filesize: 94 + maxprot: 7 + initprot: 7 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0 + size: 94 + offset: 0xF0 + align: 4 + reloff: 0x0 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x0 + reserved2: 0x0 + reserved3: 0x0 + content: 554889E589F840F6C610752985F6744C0FB7F84189F04183E00F4489C1D3EFC1E81040F6DE4080E60F89C289F1D3E209FA89C7EB1789C7C1EF10C1F8104080E60F89F1D3F86641B80F0089C20FBFC74489C1D3F80FB7CAC1E01009C85DC3 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 334 + nsyms: 14 + stroff: 558 + strsize: 704 + - cmd: LC_VERSION_MIN_IPHONEOS + cmdsize: 16 + version: 458752 + sdk: 0 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 334 + datasize: 0 +LinkEditData: + NameList: + - n_strx: 596 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 562 + n_type: 0x64 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 696 + n_type: 0x2E + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 551 + n_type: 0x24 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 77 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 449 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 181 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 265 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 1 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 348 + n_type: 0x84 + n_sect: 0 + n_desc: 0 + n_value: 0 + - n_strx: 696 + n_type: 0x24 + n_sect: 0 + n_desc: 0 + n_value: 94 + - n_strx: 696 + n_type: 0x4E + n_sect: 1 + n_desc: 0 + n_value: 94 + - n_strx: 696 + n_type: 0x64 + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 551 + n_type: 0x1F + n_sect: 1 + n_desc: 0 + n_value: 0 + StringTable: + - '' + - '/rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/ops/bit.rs' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/int/shift.rs' + - '/rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/num/uint_macros.rs' + - '/rustc/9d1b2106e23b1abd32fce1f17267604a5102f57a/library/core/src/num/int_macros.rs' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/macros.rs' + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/int/mod.rs' + - ___ashrsi3 + - compiler_builtins.f13b4771-cgu.10 + - '/Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/compiler_builtins-0.1.67/src/lib.rs/@/' + - '' + - '' + - '' + - '' + - '' + - '' + - '' +... diff --git a/llvm/test/tools/llvm-objcopy/MachO/real-world-input-copy.test b/llvm/test/tools/llvm-objcopy/MachO/real-world-input-copy.test --- a/llvm/test/tools/llvm-objcopy/MachO/real-world-input-copy.test +++ b/llvm/test/tools/llvm-objcopy/MachO/real-world-input-copy.test @@ -12,4 +12,12 @@ # RUN: llvm-objcopy %t.various-symbols.o %t.various-symbols.copy.o # RUN: cmp %t.various-symbols.o %t.various-symbols.copy.o +## Make sure darwin specific alignment is preserved in archives +# RUN: rm -rf %t; split-file %p/Inputs/unaligned_objects.yaml %t +# RUN: yaml2obj %t/first-object.yaml > %t/first.o +# RUN: yaml2obj %t/second-object.yaml > %t/second.o +# RUN: llvm-ar cr %t/lib.a %t/first.o %t/second.o +# RUN: llvm-objcopy %t/lib.a %t/lib.copy.a +# RUN: cmp %t/lib.a %t/lib.copy.a + # REQUIRES: x86-registered-target diff --git a/llvm/tools/llvm-ar/llvm-ar.cpp b/llvm/tools/llvm-ar/llvm-ar.cpp --- a/llvm/tools/llvm-ar/llvm-ar.cpp +++ b/llvm/tools/llvm-ar/llvm-ar.cpp @@ -965,6 +965,13 @@ llvm_unreachable(""); } + if (Kind == object::Archive::K_BSD) { + if (NewMembersP && !NewMembersP->empty() && NewMembersP->front().isMacho()) + Kind = object::Archive::K_DARWIN; + else if (!NewMembers.empty() && NewMembers.front().isMacho()) + Kind = object::Archive::K_DARWIN; + } + Error E = writeArchive(ArchiveName, NewMembersP ? *NewMembersP : NewMembers, Symtab, Kind, Deterministic, Thin, std::move(OldArchiveBuf));