[PATCH] [Object] Search for architecures by name in MachOUniversalBinary::getObjectForArch()

Frédéric Riss friss at apple.com
Mon Jun 22 14:55:27 PDT 2015


> On Jun 22, 2015, at 11:11 AM, Justin Bogner <mail at justinbogner.com> wrote:
> 
> Frederic Riss <friss at apple.com> writes:
>> Hi samsonov, bogner,
>> 
>> The reason we need to search by name rather than by Triple::ArchType
>> is to handle x86_64h correclty. There is no different ArchType
>> for the x86_64h architecture (it identifies itself as x86_64), and
>> this is by design. The only way to get to the x86_64h slice of an
>> universal binary is to serch by name.
> 
> So, this affects more than just x86_64h - it also applies to the armv7
> variants and generally on anything with subtargets. I'd be happier if we
> didn't have to resort to passing strings around here, but this does seem
> to be the way it's done elsewhere.

Yes. For good measure I added some arm variants in the test case I committed.
This is r240339.

> I have a couple of comments and then this LGTM.
> 
>> This issue led to hard to debug and transient symbolication failures
>> in Asan tests (it mostly works, because the files are very similar).
>> 
>> This also affects the Profiling infrastucture as it is the other user
>> of that API.
>> 
>> http://reviews.llvm.org/D10604
>> 
>> Files:
>>  include/llvm/Object/MachOUniversal.h
>>  include/llvm/ProfileData/CoverageMapping.h
>>  include/llvm/ProfileData/CoverageMappingReader.h
>>  lib/Object/MachOUniversal.cpp
>>  lib/ProfileData/CoverageMapping.cpp
>>  lib/ProfileData/CoverageMappingReader.cpp
>>  test/tools/llvm-symbolizer/Inputs/fat.x86_64h.c
>>  test/tools/llvm-symbolizer/Inputs/fat.x86_64h.o
>>  test/tools/llvm-symbolizer/fat.test
>>  tools/llvm-cov/CodeCoverage.cpp
>>  tools/llvm-symbolizer/LLVMSymbolize.cpp
>> 
>> EMAIL PREFERENCES
>>  http://reviews.llvm.org/settings/panel/emailpreferences/
>> Index: include/llvm/Object/MachOUniversal.h
>> ===================================================================
>> --- include/llvm/Object/MachOUniversal.h
>> +++ include/llvm/Object/MachOUniversal.h
>> @@ -109,7 +109,7 @@
>>   }
>> 
>>   ErrorOr<std::unique_ptr<MachOObjectFile>>
>> -  getObjectForArch(Triple::ArchType Arch) const;
>> +  getObjectForArch(StringRef ArchName) const;
>> };
>> 
>> } // namespace object
>> Index: include/llvm/ProfileData/CoverageMapping.h
>> ===================================================================
>> --- include/llvm/ProfileData/CoverageMapping.h
>> +++ include/llvm/ProfileData/CoverageMapping.h
>> @@ -410,7 +410,7 @@
>>   /// \brief Load the coverage mapping from the given files.
>>   static ErrorOr<std::unique_ptr<CoverageMapping>>
>>   load(StringRef ObjectFilename, StringRef ProfileFilename,
>> -       Triple::ArchType Arch = Triple::ArchType::UnknownArch);
>> +       StringRef Arch = StringRef());
>> 
>>   /// \brief The number of functions that couldn't have their profiles mapped.
>>   ///
>> Index: include/llvm/ProfileData/CoverageMappingReader.h
>> ===================================================================
>> --- include/llvm/ProfileData/CoverageMappingReader.h
>> +++ include/llvm/ProfileData/CoverageMappingReader.h
>> @@ -171,7 +171,7 @@
>> public:
>>   static ErrorOr<std::unique_ptr<BinaryCoverageReader>>
>>   create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
>> -         Triple::ArchType Arch = Triple::ArchType::UnknownArch);
>> +         StringRef Arch);
>> 
>>   std::error_code readNextRecord(CoverageMappingRecord &Record) override;
>> };
>> Index: lib/Object/MachOUniversal.cpp
>> ===================================================================
>> --- lib/Object/MachOUniversal.cpp
>> +++ lib/Object/MachOUniversal.cpp
>> @@ -123,25 +123,10 @@
>>   ec = std::error_code();
>> }
>> 
>> -static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) {
>> -  switch (Arch) {
>> -    case Triple::x86:    CTM = MachO::CPU_TYPE_I386; return true;
>> -    case Triple::x86_64: CTM = MachO::CPU_TYPE_X86_64; return true;
>> -    case Triple::arm:    CTM = MachO::CPU_TYPE_ARM; return true;
>> -    case Triple::sparc:  CTM = MachO::CPU_TYPE_SPARC; return true;
>> -    case Triple::ppc:    CTM = MachO::CPU_TYPE_POWERPC; return true;
>> -    case Triple::ppc64:  CTM = MachO::CPU_TYPE_POWERPC64; return true;
>> -    default: return false;
>> -  }
>> -}
>> -
>> ErrorOr<std::unique_ptr<MachOObjectFile>>
>> -MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch) const {
>> -  MachO::CPUType CTM;
>> -  if (!getCTMForArch(Arch, CTM))
>> -    return object_error::arch_not_found;
>> +MachOUniversalBinary::getObjectForArch(StringRef ArchName) const {
> 
> We should check for `Triple(Arch).getArch() == Triple::ArchType::UnknownArch`
> here and return an error.

Done.

>>   for (object_iterator I = begin_objects(), E = end_objects(); I != E; ++I) {
>> -    if (I->getCPUType() == static_cast<uint32_t>(CTM))
>> +    if (I->getArchTypeName() == ArchName)
>>       return I->getAsObjectFile();
>>   }
>>   return object_error::arch_not_found;
>> Index: lib/ProfileData/CoverageMapping.cpp
>> ===================================================================
>> --- lib/ProfileData/CoverageMapping.cpp
>> +++ lib/ProfileData/CoverageMapping.cpp
>> @@ -236,7 +236,7 @@
>> 
>> ErrorOr<std::unique_ptr<CoverageMapping>>
>> CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename,
>> -                      Triple::ArchType Arch) {
>> +                      StringRef Arch) {
>>   auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename);
>>   if (std::error_code EC = CounterMappingBuff.getError())
>>     return EC;
>> Index: lib/ProfileData/CoverageMappingReader.cpp
>> ===================================================================
>> --- lib/ProfileData/CoverageMappingReader.cpp
>> +++ lib/ProfileData/CoverageMappingReader.cpp
>> @@ -448,7 +448,7 @@
>>                                         StringRef &CoverageMapping,
>>                                         uint8_t &BytesInAddress,
>>                                         support::endianness &Endian,
>> -                                        Triple::ArchType Arch) {
>> +                                        StringRef Arch) {
>>   auto BinOrErr = object::createBinary(ObjectBuffer);
>>   if (std::error_code EC = BinOrErr.getError())
>>     return EC;
>> @@ -465,7 +465,7 @@
>>     // For any other object file, upcast and take ownership.
>>     OF.reset(cast<object::ObjectFile>(Bin.release()));
>>     // If we've asked for a particular arch, make sure they match.
>> -    if (Arch != Triple::ArchType::UnknownArch && OF->getArch() != Arch)
>> +    if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
>>       return object_error::arch_not_found;
>>   } else
>>     // We can only handle object files.
>> @@ -495,7 +495,7 @@
>> 
>> ErrorOr<std::unique_ptr<BinaryCoverageReader>>
>> BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
>> -                             Triple::ArchType Arch) {
>> +                             StringRef Arch) {
>>   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
>> 
>>   SectionData Profile;
>> Index: test/tools/llvm-symbolizer/Inputs/fat.x86_64h.c
>> ===================================================================
>> --- /dev/null
>> +++ test/tools/llvm-symbolizer/Inputs/fat.x86_64h.c
>> @@ -0,0 +1,9 @@
>> +/* Compile with:
>> +   $ clang -arch x86_64 -arch x86_64h fat.x86_64h.c -c
>> +*/
>> +
>> +#ifdef __x86_64h__
>> +void x86_64h_function() {}
>> +#else
>> +void x86_64_function() {}
>> +#endif
>> Index: test/tools/llvm-symbolizer/fat.test
>> ===================================================================
>> --- /dev/null
>> +++ test/tools/llvm-symbolizer/fat.test
>> @@ -0,0 +1,8 @@
>> +RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.x86_64h.o -default-arch=x86_64 | FileCheck --check-prefix=X86_64 %s
>> +RUN: echo 0 | llvm-symbolizer -obj=%p/Inputs/fat.x86_64h.o -default-arch=x86_64h | FileCheck --check-prefix=X86_64H %s
>> +
>> +X86_64-NOT: x86_64h_function
>> +X86_64: x86_64_function
>> +
>> +X86_64H-NOT: x86_64_function
>> +X86_64H: x86_64h_function
>> Index: tools/llvm-cov/CodeCoverage.cpp
>> ===================================================================
>> --- tools/llvm-cov/CodeCoverage.cpp
>> +++ tools/llvm-cov/CodeCoverage.cpp
>> @@ -89,7 +89,7 @@
>>       LoadedSourceFiles;
>>   bool CompareFilenamesOnly;
>>   StringMap<std::string> RemappedFilenames;
>> -  llvm::Triple::ArchType CoverageArch;
>> +  std::string CoverageArch;
> 
> We don't need this variable...
> 
>> };
>> }
>> 
>> @@ -349,15 +349,12 @@
>>       Filters.push_back(std::unique_ptr<CoverageFilter>(StatFilterer));
>>     }
>> 
>> -    if (Arch.empty())
>> -      CoverageArch = llvm::Triple::ArchType::UnknownArch;
>> -    else {
>> -      CoverageArch = Triple(Arch).getArch();
>> -      if (CoverageArch == llvm::Triple::ArchType::UnknownArch) {
>> -        errs() << "error: Unknown architecture: " << Arch << "\n";
>> -        return 1;
>> -      }
>> +    if (!Arch.empty() &&
>> +        Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) {
>> +      errs() << "error: Unknown architecture: " << Arch << "\n";
>> +      return 1;
>>     }
>> +    CoverageArch = Arch;
> 
> ... because we can just use Arch directly now.

But the member variable is used somewhere else. I left it in.

>> 
>>     for (const auto &File : InputSourceFiles) {
>>       SmallString<128> Path(File);
>> Index: tools/llvm-symbolizer/LLVMSymbolize.cpp
>> ===================================================================
>> --- tools/llvm-symbolizer/LLVMSymbolize.cpp
>> +++ tools/llvm-symbolizer/LLVMSymbolize.cpp
>> @@ -436,7 +436,7 @@
>>     if (I != ObjectFileForArch.end())
>>       return I->second;
>>     ErrorOr<std::unique_ptr<ObjectFile>> ParsedObj =
>> -        UB->getObjectForArch(Triple(ArchName).getArch());
>> +        UB->getObjectForArch(ArchName);
>>     if (ParsedObj) {
>>       Res = ParsedObj.get().get();
>>       ParsedBinariesAndObjects.push_back(std::move(ParsedObj.get()));





More information about the llvm-commits mailing list