mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	[dsymutil] Implement support for universal mach-o object files.
This patch allows llvm-dsymutil to read universal (aka fat) macho object files and archives. The patch touches nearly everything in the BinaryHolder, but it is fairly mechinical: the methods that returned MemoryBufferRefs or ObjectFiles now return a vector of those, and the high-level access function takes a triple argument to select the architecture. There is no support yet for handling fat executables and thus no support for writing fat object files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243096 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		
							
								
								
									
										13
									
								
								test/tools/dsymutil/ARM/fat-arch-not-found.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								test/tools/dsymutil/ARM/fat-arch-not-found.test
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					# REQUIRES: object-emission
 | 
				
			||||||
 | 
					# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - 2>&1 | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					triple:          'armv7-apple-darwin'
 | 
				
			||||||
 | 
					objects:
 | 
				
			||||||
 | 
					  - filename: libfat-test.a(fat-test.o)
 | 
				
			||||||
 | 
					    symbols:
 | 
				
			||||||
 | 
					      - { sym: _armv7_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK: libfat-test.a(fat-test.o): No object file for requested architecture
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								test/tools/dsymutil/ARM/lit.local.cfg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/tools/dsymutil/ARM/lit.local.cfg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					if not 'X86' in config.root.targets:
 | 
				
			||||||
 | 
					    config.unsupported = True
 | 
				
			||||||
							
								
								
									
										17
									
								
								test/tools/dsymutil/Inputs/fat-test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								test/tools/dsymutil/Inputs/fat-test.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					/* Compile with:
 | 
				
			||||||
 | 
					   clang -c -g -arch x86_64h -arch x86_64 -arch i386 fat-test.c
 | 
				
			||||||
 | 
					   libtool -static -o libfat-test.a fat-test.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   To reduce the size of the fat .o:
 | 
				
			||||||
 | 
					   lipo -thin i386 -o fat-test.i386.o fat-test.o 
 | 
				
			||||||
 | 
					   lipo -thin x86_64 -o fat-test.x86_64.o fat-test.o 
 | 
				
			||||||
 | 
					   lipo -thin x86_64h -o fat-test.x86_64h.o fat-test.o 
 | 
				
			||||||
 | 
					   lipo -create -arch x86_64h fat-test.x86_64h.o -arch x86_64 fat-test.x86_64.o -arch i386 fat-test.i386.o -o fat-test.o -segalign i386 8 -segalign x86_64 8 -segalign x86_64h 8
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifdef __x86_64h__
 | 
				
			||||||
 | 
					int x86_64h_var;
 | 
				
			||||||
 | 
					#elif defined(__x86_64__)
 | 
				
			||||||
 | 
					int x86_64_var;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					int i386_var;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								test/tools/dsymutil/Inputs/fat-test.o
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/tools/dsymutil/Inputs/fat-test.o
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								test/tools/dsymutil/Inputs/libfat-test.a
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/tools/dsymutil/Inputs/libfat-test.a
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										16
									
								
								test/tools/dsymutil/X86/fat-archive-input-i386.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								test/tools/dsymutil/X86/fat-archive-input-i386.test
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# REQUIRES: object-emission
 | 
				
			||||||
 | 
					# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					triple:          'i386-apple-darwin'
 | 
				
			||||||
 | 
					objects:
 | 
				
			||||||
 | 
					  - filename: libfat-test.a(fat-test.o)
 | 
				
			||||||
 | 
					    symbols:
 | 
				
			||||||
 | 
					      - { sym: _i386_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK: .debug_info contents:
 | 
				
			||||||
 | 
					# CHECK: DW_TAG_variable
 | 
				
			||||||
 | 
					# CHECK-NOT: {{DW_TAG|NULL}}
 | 
				
			||||||
 | 
					# CHECK:  DW_AT_name{{.*}}"i386_var"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								test/tools/dsymutil/X86/fat-object-input-x86_64.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								test/tools/dsymutil/X86/fat-object-input-x86_64.test
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# REQUIRES: object-emission
 | 
				
			||||||
 | 
					# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					triple:          'x86_64-apple-darwin'
 | 
				
			||||||
 | 
					objects:
 | 
				
			||||||
 | 
					  - filename: fat-test.o
 | 
				
			||||||
 | 
					    symbols:
 | 
				
			||||||
 | 
					      - { sym: _x86_64_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK: .debug_info contents:
 | 
				
			||||||
 | 
					# CHECK: DW_TAG_variable
 | 
				
			||||||
 | 
					# CHECK-NOT: {{DW_TAG|NULL}}
 | 
				
			||||||
 | 
					# CHECK:  DW_AT_name{{.*}}"x86_64_var"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								test/tools/dsymutil/X86/fat-object-input-x86_64h.test
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								test/tools/dsymutil/X86/fat-object-input-x86_64h.test
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# REQUIRES: object-emission
 | 
				
			||||||
 | 
					# RUN: llvm-dsymutil -oso-prepend-path=%p/../Inputs -y %s -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					triple:          'x86_64h-apple-darwin'
 | 
				
			||||||
 | 
					objects:
 | 
				
			||||||
 | 
					  - filename: fat-test.o
 | 
				
			||||||
 | 
					    symbols:
 | 
				
			||||||
 | 
					      - { sym: _x86_64h_var, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
 | 
				
			||||||
 | 
					...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# CHECK: .debug_info contents:
 | 
				
			||||||
 | 
					# CHECK: DW_TAG_variable
 | 
				
			||||||
 | 
					# CHECK-NOT: {{DW_TAG|NULL}}
 | 
				
			||||||
 | 
					# CHECK:  DW_AT_name{{.*}}"x86_64h_var"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -28,30 +28,44 @@ Triple BinaryHolder::getTriple(const object::MachOObjectFile &Obj) {
 | 
				
			|||||||
  return ThumbTriple.getArch() ? ThumbTriple : T;
 | 
					  return ThumbTriple.getArch() ? ThumbTriple : T;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static std::vector<MemoryBufferRef>
 | 
				
			||||||
 | 
					getMachOFatMemoryBuffers(StringRef Filename, MemoryBuffer &Mem,
 | 
				
			||||||
 | 
					                         object::MachOUniversalBinary &Fat) {
 | 
				
			||||||
 | 
					  std::vector<MemoryBufferRef> Buffers;
 | 
				
			||||||
 | 
					  StringRef FatData = Fat.getData();
 | 
				
			||||||
 | 
					  for (auto It = Fat.begin_objects(), End = Fat.end_objects(); It != End;
 | 
				
			||||||
 | 
					       ++It) {
 | 
				
			||||||
 | 
					    StringRef ObjData = FatData.substr(It->getOffset(), It->getSize());
 | 
				
			||||||
 | 
					    Buffers.emplace_back(ObjData, Filename);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return Buffers;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void BinaryHolder::changeBackingMemoryBuffer(
 | 
					void BinaryHolder::changeBackingMemoryBuffer(
 | 
				
			||||||
    std::unique_ptr<MemoryBuffer> &&Buf) {
 | 
					    std::unique_ptr<MemoryBuffer> &&Buf) {
 | 
				
			||||||
  CurrentArchive.reset();
 | 
					  CurrentArchives.clear();
 | 
				
			||||||
  CurrentObjectFile.reset();
 | 
					  CurrentObjectFiles.clear();
 | 
				
			||||||
 | 
					  CurrentFatBinary.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CurrentMemoryBuffer = std::move(Buf);
 | 
					  CurrentMemoryBuffer = std::move(Buf);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ErrorOr<MemoryBufferRef>
 | 
					ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
BinaryHolder::GetMemoryBufferForFile(StringRef Filename,
 | 
					BinaryHolder::GetMemoryBuffersForFile(StringRef Filename,
 | 
				
			||||||
                                      sys::TimeValue Timestamp) {
 | 
					                                      sys::TimeValue Timestamp) {
 | 
				
			||||||
  if (Verbose)
 | 
					  if (Verbose)
 | 
				
			||||||
    outs() << "trying to open '" << Filename << "'\n";
 | 
					    outs() << "trying to open '" << Filename << "'\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Try that first as it doesn't involve any filesystem access.
 | 
					  // Try that first as it doesn't involve any filesystem access.
 | 
				
			||||||
  if (auto ErrOrArchiveMember = GetArchiveMemberBuffer(Filename, Timestamp))
 | 
					  if (auto ErrOrArchiveMembers = GetArchiveMemberBuffers(Filename, Timestamp))
 | 
				
			||||||
    return *ErrOrArchiveMember;
 | 
					    return *ErrOrArchiveMembers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // If the name ends with a closing paren, there is a huge chance
 | 
					  // If the name ends with a closing paren, there is a huge chance
 | 
				
			||||||
  // it is an archive member specification.
 | 
					  // it is an archive member specification.
 | 
				
			||||||
  if (Filename.endswith(")"))
 | 
					  if (Filename.endswith(")"))
 | 
				
			||||||
    if (auto ErrOrArchiveMember =
 | 
					    if (auto ErrOrArchiveMembers =
 | 
				
			||||||
            MapArchiveAndGetMemberBuffer(Filename, Timestamp))
 | 
					            MapArchiveAndGetMemberBuffers(Filename, Timestamp))
 | 
				
			||||||
      return *ErrOrArchiveMember;
 | 
					      return *ErrOrArchiveMembers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Otherwise, just try opening a standard file. If this is an
 | 
					  // Otherwise, just try opening a standard file. If this is an
 | 
				
			||||||
  // archive member specifiaction and any of the above didn't handle it
 | 
					  // archive member specifiaction and any of the above didn't handle it
 | 
				
			||||||
@@ -65,24 +79,38 @@ BinaryHolder::GetMemoryBufferForFile(StringRef Filename,
 | 
				
			|||||||
  changeBackingMemoryBuffer(std::move(*ErrOrFile));
 | 
					  changeBackingMemoryBuffer(std::move(*ErrOrFile));
 | 
				
			||||||
  if (Verbose)
 | 
					  if (Verbose)
 | 
				
			||||||
    outs() << "\tloaded file.\n";
 | 
					    outs() << "\tloaded file.\n";
 | 
				
			||||||
  return CurrentMemoryBuffer->getMemBufferRef();
 | 
					
 | 
				
			||||||
 | 
					  auto ErrOrFat = object::MachOUniversalBinary::create(
 | 
				
			||||||
 | 
					      CurrentMemoryBuffer->getMemBufferRef());
 | 
				
			||||||
 | 
					  if (ErrOrFat.getError()) {
 | 
				
			||||||
 | 
					    // Not a fat binary must be a standard one. Return a one element vector.
 | 
				
			||||||
 | 
					    return std::vector<MemoryBufferRef>{CurrentMemoryBuffer->getMemBufferRef()};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  CurrentFatBinary = std::move(*ErrOrFat);
 | 
				
			||||||
 | 
					  return getMachOFatMemoryBuffers(Filename, *CurrentMemoryBuffer,
 | 
				
			||||||
 | 
					                                  *CurrentFatBinary);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ErrorOr<MemoryBufferRef>
 | 
					ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
BinaryHolder::GetArchiveMemberBuffer(StringRef Filename,
 | 
					BinaryHolder::GetArchiveMemberBuffers(StringRef Filename,
 | 
				
			||||||
                                      sys::TimeValue Timestamp) {
 | 
					                                      sys::TimeValue Timestamp) {
 | 
				
			||||||
  if (!CurrentArchive)
 | 
					  if (CurrentArchives.empty())
 | 
				
			||||||
    return make_error_code(errc::no_such_file_or_directory);
 | 
					    return make_error_code(errc::no_such_file_or_directory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  StringRef CurArchiveName = CurrentArchive->getFileName();
 | 
					  StringRef CurArchiveName = CurrentArchives.front()->getFileName();
 | 
				
			||||||
  if (!Filename.startswith(Twine(CurArchiveName, "(").str()))
 | 
					  if (!Filename.startswith(Twine(CurArchiveName, "(").str()))
 | 
				
			||||||
    return make_error_code(errc::no_such_file_or_directory);
 | 
					    return make_error_code(errc::no_such_file_or_directory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Remove the archive name and the parens around the archive member name.
 | 
					  // Remove the archive name and the parens around the archive member name.
 | 
				
			||||||
  Filename = Filename.substr(CurArchiveName.size() + 1).drop_back();
 | 
					  Filename = Filename.substr(CurArchiveName.size() + 1).drop_back();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  std::vector<MemoryBufferRef> Buffers;
 | 
				
			||||||
 | 
					  Buffers.reserve(CurrentArchives.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const auto &CurrentArchive : CurrentArchives) {
 | 
				
			||||||
    for (const auto &Child : CurrentArchive->children()) {
 | 
					    for (const auto &Child : CurrentArchive->children()) {
 | 
				
			||||||
    if (auto NameOrErr = Child.getName())
 | 
					      if (auto NameOrErr = Child.getName()) {
 | 
				
			||||||
        if (*NameOrErr == Filename) {
 | 
					        if (*NameOrErr == Filename) {
 | 
				
			||||||
          if (Timestamp != sys::TimeValue::PosixZeroTime() &&
 | 
					          if (Timestamp != sys::TimeValue::PosixZeroTime() &&
 | 
				
			||||||
              Timestamp != Child.getLastModified()) {
 | 
					              Timestamp != Child.getLastModified()) {
 | 
				
			||||||
@@ -92,15 +120,22 @@ BinaryHolder::GetArchiveMemberBuffer(StringRef Filename,
 | 
				
			|||||||
          }
 | 
					          }
 | 
				
			||||||
          if (Verbose)
 | 
					          if (Verbose)
 | 
				
			||||||
            outs() << "\tfound member in current archive.\n";
 | 
					            outs() << "\tfound member in current archive.\n";
 | 
				
			||||||
        return Child.getMemoryBufferRef();
 | 
					          auto ErrOrMem = Child.getMemoryBufferRef();
 | 
				
			||||||
 | 
					          if (auto Err = ErrOrMem.getError())
 | 
				
			||||||
 | 
					            return Err;
 | 
				
			||||||
 | 
					          Buffers.push_back(*ErrOrMem);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (Buffers.empty())
 | 
				
			||||||
    return make_error_code(errc::no_such_file_or_directory);
 | 
					    return make_error_code(errc::no_such_file_or_directory);
 | 
				
			||||||
 | 
					  return Buffers;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ErrorOr<MemoryBufferRef>
 | 
					ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename,
 | 
					BinaryHolder::MapArchiveAndGetMemberBuffers(StringRef Filename,
 | 
				
			||||||
                                            sys::TimeValue Timestamp) {
 | 
					                                            sys::TimeValue Timestamp) {
 | 
				
			||||||
  StringRef ArchiveFilename = Filename.substr(0, Filename.find('('));
 | 
					  StringRef ArchiveFilename = Filename.substr(0, Filename.find('('));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,29 +147,60 @@ BinaryHolder::MapArchiveAndGetMemberBuffer(StringRef Filename,
 | 
				
			|||||||
    outs() << "\topened new archive '" << ArchiveFilename << "'\n";
 | 
					    outs() << "\topened new archive '" << ArchiveFilename << "'\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  changeBackingMemoryBuffer(std::move(*ErrOrBuff));
 | 
					  changeBackingMemoryBuffer(std::move(*ErrOrBuff));
 | 
				
			||||||
  auto ErrOrArchive =
 | 
					  std::vector<MemoryBufferRef> ArchiveBuffers;
 | 
				
			||||||
      object::Archive::create(CurrentMemoryBuffer->getMemBufferRef());
 | 
					  auto ErrOrFat = object::MachOUniversalBinary::create(
 | 
				
			||||||
 | 
					      CurrentMemoryBuffer->getMemBufferRef());
 | 
				
			||||||
 | 
					  if (ErrOrFat.getError()) {
 | 
				
			||||||
 | 
					    // Not a fat binary must be a standard one.
 | 
				
			||||||
 | 
					    ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef());
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    CurrentFatBinary = std::move(*ErrOrFat);
 | 
				
			||||||
 | 
					    ArchiveBuffers = getMachOFatMemoryBuffers(
 | 
				
			||||||
 | 
					        ArchiveFilename, *CurrentMemoryBuffer, *CurrentFatBinary);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (auto MemRef : ArchiveBuffers) {
 | 
				
			||||||
 | 
					    auto ErrOrArchive = object::Archive::create(MemRef);
 | 
				
			||||||
    if (auto Err = ErrOrArchive.getError())
 | 
					    if (auto Err = ErrOrArchive.getError())
 | 
				
			||||||
      return Err;
 | 
					      return Err;
 | 
				
			||||||
 | 
					    CurrentArchives.push_back(std::move(*ErrOrArchive));
 | 
				
			||||||
  CurrentArchive = std::move(*ErrOrArchive);
 | 
					  }
 | 
				
			||||||
 | 
					  return GetArchiveMemberBuffers(Filename, Timestamp);
 | 
				
			||||||
  return GetArchiveMemberBuffer(Filename, Timestamp);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ErrorOr<const object::ObjectFile &>
 | 
					ErrorOr<const object::ObjectFile &>
 | 
				
			||||||
BinaryHolder::GetObjectFile(StringRef Filename, sys::TimeValue Timestamp) {
 | 
					BinaryHolder::getObjfileForArch(const Triple &T) {
 | 
				
			||||||
  auto ErrOrMemBufferRef = GetMemoryBufferForFile(Filename, Timestamp);
 | 
					  for (const auto &Obj : CurrentObjectFiles) {
 | 
				
			||||||
  if (auto Err = ErrOrMemBufferRef.getError())
 | 
					    if (const auto *MachO = dyn_cast<object::MachOObjectFile>(Obj.get())) {
 | 
				
			||||||
 | 
					      if (getTriple(*MachO).str() == T.str())
 | 
				
			||||||
 | 
					        return *MachO;
 | 
				
			||||||
 | 
					    } else if (Obj->getArch() == T.getArch())
 | 
				
			||||||
 | 
					      return *Obj;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return make_error_code(object::object_error::arch_not_found);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ErrorOr<std::vector<const object::ObjectFile *>>
 | 
				
			||||||
 | 
					BinaryHolder::GetObjectFiles(StringRef Filename, sys::TimeValue Timestamp) {
 | 
				
			||||||
 | 
					  auto ErrOrMemBufferRefs = GetMemoryBuffersForFile(Filename, Timestamp);
 | 
				
			||||||
 | 
					  if (auto Err = ErrOrMemBufferRefs.getError())
 | 
				
			||||||
    return Err;
 | 
					    return Err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto ErrOrObjectFile =
 | 
					  std::vector<const object::ObjectFile *> Objects;
 | 
				
			||||||
      object::ObjectFile::createObjectFile(*ErrOrMemBufferRef);
 | 
					  Objects.reserve(ErrOrMemBufferRefs->size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  CurrentObjectFiles.clear();
 | 
				
			||||||
 | 
					  for (auto MemBuf : *ErrOrMemBufferRefs) {
 | 
				
			||||||
 | 
					    auto ErrOrObjectFile = object::ObjectFile::createObjectFile(MemBuf);
 | 
				
			||||||
    if (auto Err = ErrOrObjectFile.getError())
 | 
					    if (auto Err = ErrOrObjectFile.getError())
 | 
				
			||||||
      return Err;
 | 
					      return Err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CurrentObjectFile = std::move(*ErrOrObjectFile);
 | 
					    Objects.push_back(ErrOrObjectFile->get());
 | 
				
			||||||
  return *CurrentObjectFile;
 | 
					    CurrentObjectFiles.push_back(std::move(*ErrOrObjectFile));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return std::move(Objects);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@
 | 
				
			|||||||
#include "llvm/ADT/Triple.h"
 | 
					#include "llvm/ADT/Triple.h"
 | 
				
			||||||
#include "llvm/Object/Archive.h"
 | 
					#include "llvm/Object/Archive.h"
 | 
				
			||||||
#include "llvm/Object/Error.h"
 | 
					#include "llvm/Object/Error.h"
 | 
				
			||||||
 | 
					#include "llvm/Object/MachOUniversal.h"
 | 
				
			||||||
#include "llvm/Object/ObjectFile.h"
 | 
					#include "llvm/Object/ObjectFile.h"
 | 
				
			||||||
#include "llvm/Support/Errc.h"
 | 
					#include "llvm/Support/Errc.h"
 | 
				
			||||||
#include "llvm/Support/ErrorOr.h"
 | 
					#include "llvm/Support/ErrorOr.h"
 | 
				
			||||||
@@ -37,77 +38,95 @@ namespace dsymutil {
 | 
				
			|||||||
/// meaning that a mapping request will invalidate the previous memory
 | 
					/// meaning that a mapping request will invalidate the previous memory
 | 
				
			||||||
/// mapping.
 | 
					/// mapping.
 | 
				
			||||||
class BinaryHolder {
 | 
					class BinaryHolder {
 | 
				
			||||||
  std::unique_ptr<object::Archive> CurrentArchive;
 | 
					  std::vector<std::unique_ptr<object::Archive>> CurrentArchives;
 | 
				
			||||||
  std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
 | 
					  std::unique_ptr<MemoryBuffer> CurrentMemoryBuffer;
 | 
				
			||||||
  std::unique_ptr<object::ObjectFile> CurrentObjectFile;
 | 
					  std::vector<std::unique_ptr<object::ObjectFile>> CurrentObjectFiles;
 | 
				
			||||||
 | 
					  std::unique_ptr<object::MachOUniversalBinary> CurrentFatBinary;
 | 
				
			||||||
  bool Verbose;
 | 
					  bool Verbose;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Get the MemoryBufferRef for the file specification in \p
 | 
					  /// Get the MemoryBufferRefs for the file specification in \p
 | 
				
			||||||
  /// Filename from the current archive.
 | 
					  /// Filename from the current archive. Multiple buffers are returned
 | 
				
			||||||
 | 
					  /// when there are multiple architectures available for the
 | 
				
			||||||
 | 
					  /// requested file.
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// This function performs no system calls, it just looks up a
 | 
					  /// This function performs no system calls, it just looks up a
 | 
				
			||||||
  /// potential match for the given \p Filename in the currently
 | 
					  /// potential match for the given \p Filename in the currently
 | 
				
			||||||
  /// mapped archive if there is one.
 | 
					  /// mapped archive if there is one.
 | 
				
			||||||
  ErrorOr<MemoryBufferRef> GetArchiveMemberBuffer(StringRef Filename,
 | 
					  ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
                                                  sys::TimeValue Timestamp);
 | 
					  GetArchiveMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Interpret Filename as an archive member specification,
 | 
					  /// Interpret Filename as an archive member specification map the
 | 
				
			||||||
  /// map the corresponding archive to memory and return the
 | 
					  /// corresponding archive to memory and return the MemoryBufferRefs
 | 
				
			||||||
  /// MemoryBufferRef corresponding to the described member.
 | 
					  /// corresponding to the described member. Multiple buffers are
 | 
				
			||||||
  ErrorOr<MemoryBufferRef>
 | 
					  /// returned when there are multiple architectures available for the
 | 
				
			||||||
  MapArchiveAndGetMemberBuffer(StringRef Filename, sys::TimeValue Timestamp);
 | 
					  /// requested file.
 | 
				
			||||||
 | 
					  ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
 | 
					  MapArchiveAndGetMemberBuffers(StringRef Filename, sys::TimeValue Timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Return the MemoryBufferRef that holds the memory
 | 
					  /// Return the MemoryBufferRef that holds the memory mapping for the
 | 
				
			||||||
  /// mapping for the given \p Filename. This function will try to
 | 
					  /// given \p Filename. This function will try to parse archive
 | 
				
			||||||
  /// parse archive member specifications of the form
 | 
					  /// member specifications of the form /path/to/archive.a(member.o).
 | 
				
			||||||
  /// /path/to/archive.a(member.o).
 | 
					 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// The returned MemoryBufferRef points to a buffer owned by this
 | 
					  /// The returned MemoryBufferRefs points to a buffer owned by this
 | 
				
			||||||
  /// object. The buffer is valid until the next call to
 | 
					  /// object. The buffer is valid until the next call to
 | 
				
			||||||
  /// GetMemoryBufferForFile() on this object.
 | 
					  /// GetMemoryBufferForFile() on this object.
 | 
				
			||||||
  ErrorOr<MemoryBufferRef> GetMemoryBufferForFile(StringRef Filename,
 | 
					  /// Multiple buffers are returned when there are multiple
 | 
				
			||||||
                                                  sys::TimeValue Timestamp);
 | 
					  /// architectures available for the requested file.
 | 
				
			||||||
 | 
					  ErrorOr<std::vector<MemoryBufferRef>>
 | 
				
			||||||
 | 
					  GetMemoryBuffersForFile(StringRef Filename, sys::TimeValue Timestamp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
 | 
					  void changeBackingMemoryBuffer(std::unique_ptr<MemoryBuffer> &&MemBuf);
 | 
				
			||||||
 | 
					  ErrorOr<const object::ObjectFile &> getObjfileForArch(const Triple &T);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  BinaryHolder(bool Verbose) : Verbose(Verbose) {}
 | 
					  BinaryHolder(bool Verbose) : Verbose(Verbose) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Get the ObjectFile designated by the \p Filename. This
 | 
					  /// Get the ObjectFiles designated by the \p Filename. This
 | 
				
			||||||
  /// might be an archive member specification of the form
 | 
					  /// might be an archive member specification of the form
 | 
				
			||||||
  /// /path/to/archive.a(member.o).
 | 
					  /// /path/to/archive.a(member.o).
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
  /// Calling this function invalidates the previous mapping owned by
 | 
					  /// Calling this function invalidates the previous mapping owned by
 | 
				
			||||||
  /// the BinaryHolder.
 | 
					  /// the BinaryHolder. Multiple buffers are returned when there are
 | 
				
			||||||
  ErrorOr<const object::ObjectFile &>
 | 
					  /// multiple architectures available for the requested file.
 | 
				
			||||||
  GetObjectFile(StringRef Filename,
 | 
					  ErrorOr<std::vector<const object::ObjectFile *>>
 | 
				
			||||||
 | 
					  GetObjectFiles(StringRef Filename,
 | 
				
			||||||
                 sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime());
 | 
					                 sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Wraps GetObjectFile() to return a derived ObjectFile type.
 | 
					  /// Wraps GetObjectFiles() to return a derived ObjectFile type.
 | 
				
			||||||
  template <typename ObjectFileType>
 | 
					  template <typename ObjectFileType>
 | 
				
			||||||
  ErrorOr<const ObjectFileType &>
 | 
					  ErrorOr<std::vector<const ObjectFileType *>>
 | 
				
			||||||
  GetFileAs(StringRef Filename,
 | 
					  GetFilesAs(StringRef Filename,
 | 
				
			||||||
             sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) {
 | 
					             sys::TimeValue Timestamp = sys::TimeValue::PosixZeroTime()) {
 | 
				
			||||||
    auto ErrOrObjFile = GetObjectFile(Filename);
 | 
					    auto ErrOrObjFile = GetObjectFiles(Filename, Timestamp);
 | 
				
			||||||
    if (auto Err = ErrOrObjFile.getError())
 | 
					    if (auto Err = ErrOrObjFile.getError())
 | 
				
			||||||
      return Err;
 | 
					      return Err;
 | 
				
			||||||
    if (const auto *Derived = dyn_cast<ObjectFileType>(CurrentObjectFile.get()))
 | 
					
 | 
				
			||||||
      return *Derived;
 | 
					    std::vector<const ObjectFileType *> Objects;
 | 
				
			||||||
 | 
					    Objects.reserve((*ErrOrObjFile).size());
 | 
				
			||||||
 | 
					    for (const auto &Obj : *ErrOrObjFile) {
 | 
				
			||||||
 | 
					      const auto *Derived = dyn_cast<ObjectFileType>(Obj);
 | 
				
			||||||
 | 
					      if (!Derived)
 | 
				
			||||||
        return make_error_code(object::object_error::invalid_file_type);
 | 
					        return make_error_code(object::object_error::invalid_file_type);
 | 
				
			||||||
 | 
					      Objects.push_back(Derived);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return std::move(Objects);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Access the currently owned ObjectFile. As successfull
 | 
					  /// Access the currently owned ObjectFile with architecture \p T. As
 | 
				
			||||||
  /// call to GetObjectFile() or GetFileAs() must have been performed
 | 
					  /// successfull call to GetObjectFiles() or GetFilesAs() must have
 | 
				
			||||||
  /// before calling this.
 | 
					  /// been performed before calling this.
 | 
				
			||||||
  const object::ObjectFile &Get() {
 | 
					  ErrorOr<const object::ObjectFile &> Get(const Triple &T) {
 | 
				
			||||||
    assert(CurrentObjectFile);
 | 
					    return getObjfileForArch(T);
 | 
				
			||||||
    return *CurrentObjectFile;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// \brief Access to a derived version of the currently owned
 | 
					  /// Access to a derived version of the currently owned
 | 
				
			||||||
  /// ObjectFile. The conversion must be known to be valid.
 | 
					  /// ObjectFile. The conversion must be known to be valid.
 | 
				
			||||||
  template <typename ObjectFileType> const ObjectFileType &GetAs() {
 | 
					  template <typename ObjectFileType>
 | 
				
			||||||
    return cast<ObjectFileType>(*CurrentObjectFile);
 | 
					  ErrorOr<const ObjectFileType &> GetAs(const Triple &T) {
 | 
				
			||||||
 | 
					    auto ErrOrObj = Get(T);
 | 
				
			||||||
 | 
					    if (auto Err = ErrOrObj.getError())
 | 
				
			||||||
 | 
					      return Err;
 | 
				
			||||||
 | 
					    return cast<ObjectFileType>(*ErrOrObj);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static Triple getTriple(const object::MachOObjectFile &Obj);
 | 
					  static Triple getTriple(const object::MachOObjectFile &Obj);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -178,9 +178,9 @@ SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>>::element(
 | 
				
			|||||||
void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
 | 
					void MappingTraits<dsymutil::DebugMap>::mapping(IO &io,
 | 
				
			||||||
                                                dsymutil::DebugMap &DM) {
 | 
					                                                dsymutil::DebugMap &DM) {
 | 
				
			||||||
  io.mapRequired("triple", DM.BinaryTriple);
 | 
					  io.mapRequired("triple", DM.BinaryTriple);
 | 
				
			||||||
  io.mapOptional("objects", DM.Objects);
 | 
					 | 
				
			||||||
  if (void *Ctxt = io.getContext())
 | 
					  if (void *Ctxt = io.getContext())
 | 
				
			||||||
    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM.BinaryTriple;
 | 
					    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM.BinaryTriple;
 | 
				
			||||||
 | 
					  io.mapOptional("objects", DM.Objects);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
 | 
					void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
 | 
				
			||||||
@@ -188,9 +188,9 @@ void MappingTraits<std::unique_ptr<dsymutil::DebugMap>>::mapping(
 | 
				
			|||||||
  if (!DM)
 | 
					  if (!DM)
 | 
				
			||||||
    DM.reset(new DebugMap());
 | 
					    DM.reset(new DebugMap());
 | 
				
			||||||
  io.mapRequired("triple", DM->BinaryTriple);
 | 
					  io.mapRequired("triple", DM->BinaryTriple);
 | 
				
			||||||
  io.mapOptional("objects", DM->Objects);
 | 
					 | 
				
			||||||
  if (void *Ctxt = io.getContext())
 | 
					  if (void *Ctxt = io.getContext())
 | 
				
			||||||
    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
 | 
					    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = DM->BinaryTriple;
 | 
				
			||||||
 | 
					  io.mapOptional("objects", DM->Objects);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
 | 
					MappingTraits<dsymutil::DebugMapObject>::YamlDMO::YamlDMO(
 | 
				
			||||||
@@ -210,11 +210,11 @@ MappingTraits<dsymutil::DebugMapObject>::YamlDMO::denormalize(IO &IO) {
 | 
				
			|||||||
  StringMap<uint64_t> SymbolAddresses;
 | 
					  StringMap<uint64_t> SymbolAddresses;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sys::path::append(Path, Filename);
 | 
					  sys::path::append(Path, Filename);
 | 
				
			||||||
  auto ErrOrObjectFile = BinHolder.GetObjectFile(Path);
 | 
					  auto ErrOrObjectFiles = BinHolder.GetObjectFiles(Path);
 | 
				
			||||||
  if (auto EC = ErrOrObjectFile.getError()) {
 | 
					  if (auto EC = ErrOrObjectFiles.getError()) {
 | 
				
			||||||
    llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
 | 
					    llvm::errs() << "warning: Unable to open " << Path << " " << EC.message()
 | 
				
			||||||
                 << '\n';
 | 
					                 << '\n';
 | 
				
			||||||
  } else {
 | 
					  } else if (auto ErrOrObjectFile = BinHolder.Get(Ctxt.BinaryTriple)) {
 | 
				
			||||||
    // Rewrite the object file symbol addresses in the debug map. The
 | 
					    // Rewrite the object file symbol addresses in the debug map. The
 | 
				
			||||||
    // YAML input is mainly used to test llvm-dsymutil without
 | 
					    // YAML input is mainly used to test llvm-dsymutil without
 | 
				
			||||||
    // requiring binaries checked-in. If we generate the object files
 | 
					    // requiring binaries checked-in. If we generate the object files
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1410,6 +1410,11 @@ private:
 | 
				
			|||||||
                     const DWARFDebugInfoEntryMinimal *DIE = nullptr) const;
 | 
					                     const DWARFDebugInfoEntryMinimal *DIE = nullptr) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool createStreamer(Triple TheTriple, StringRef OutputFilename);
 | 
					  bool createStreamer(Triple TheTriple, StringRef OutputFilename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// \brief Attempt to load a debug object from disk.
 | 
				
			||||||
 | 
					  ErrorOr<const object::ObjectFile &> loadObject(BinaryHolder &BinaryHolder,
 | 
				
			||||||
 | 
					                                                 DebugMapObject &Obj,
 | 
				
			||||||
 | 
					                                                 const DebugMap &Map);
 | 
				
			||||||
  /// @}
 | 
					  /// @}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
@@ -3008,6 +3013,19 @@ void DwarfLinker::patchFrameInfoForObject(const DebugMapObject &DMO,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ErrorOr<const object::ObjectFile &>
 | 
				
			||||||
 | 
					DwarfLinker::loadObject(BinaryHolder &BinaryHolder, DebugMapObject &Obj,
 | 
				
			||||||
 | 
					                        const DebugMap &Map) {
 | 
				
			||||||
 | 
					  auto ErrOrObjs =
 | 
				
			||||||
 | 
					      BinaryHolder.GetObjectFiles(Obj.getObjectFilename(), Obj.getTimestamp());
 | 
				
			||||||
 | 
					  if (std::error_code EC = ErrOrObjs.getError())
 | 
				
			||||||
 | 
					    reportWarning(Twine(Obj.getObjectFilename()) + ": " + EC.message());
 | 
				
			||||||
 | 
					  auto ErrOrObj = BinaryHolder.Get(Map.getTriple());
 | 
				
			||||||
 | 
					  if (std::error_code EC = ErrOrObj.getError())
 | 
				
			||||||
 | 
					    reportWarning(Twine(Obj.getObjectFilename()) + ": " + EC.message());
 | 
				
			||||||
 | 
					  return ErrOrObj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DwarfLinker::link(const DebugMap &Map) {
 | 
					bool DwarfLinker::link(const DebugMap &Map) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (Map.begin() == Map.end()) {
 | 
					  if (Map.begin() == Map.end()) {
 | 
				
			||||||
@@ -3027,12 +3045,9 @@ bool DwarfLinker::link(const DebugMap &Map) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (Options.Verbose)
 | 
					    if (Options.Verbose)
 | 
				
			||||||
      outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
 | 
					      outs() << "DEBUG MAP OBJECT: " << Obj->getObjectFilename() << "\n";
 | 
				
			||||||
    auto ErrOrObj =
 | 
					    auto ErrOrObj = loadObject(BinHolder, *Obj, Map);
 | 
				
			||||||
        BinHolder.GetObjectFile(Obj->getObjectFilename(), Obj->getTimestamp());
 | 
					    if (!ErrOrObj)
 | 
				
			||||||
    if (std::error_code EC = ErrOrObj.getError()) {
 | 
					 | 
				
			||||||
      reportWarning(Twine(Obj->getObjectFilename()) + ": " + EC.message());
 | 
					 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Look for relocations that correspond to debug map entries.
 | 
					    // Look for relocations that correspond to debug map entries.
 | 
				
			||||||
    if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
 | 
					    if (!findValidRelocsInDebugInfo(*ErrOrObj, *Obj)) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,8 +58,8 @@ private:
 | 
				
			|||||||
  void switchToNewDebugMapObject(StringRef Filename, sys::TimeValue Timestamp);
 | 
					  void switchToNewDebugMapObject(StringRef Filename, sys::TimeValue Timestamp);
 | 
				
			||||||
  void resetParserState();
 | 
					  void resetParserState();
 | 
				
			||||||
  uint64_t getMainBinarySymbolAddress(StringRef Name);
 | 
					  uint64_t getMainBinarySymbolAddress(StringRef Name);
 | 
				
			||||||
  void loadMainBinarySymbols();
 | 
					  void loadMainBinarySymbols(const MachOObjectFile &MainBinary);
 | 
				
			||||||
  void loadCurrentObjectFileSymbols();
 | 
					  void loadCurrentObjectFileSymbols(const object::MachOObjectFile &Obj);
 | 
				
			||||||
  void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
 | 
					  void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
 | 
				
			||||||
                                  uint8_t SectionIndex, uint16_t Flags,
 | 
					                                  uint8_t SectionIndex, uint16_t Flags,
 | 
				
			||||||
                                  uint64_t Value);
 | 
					                                  uint64_t Value);
 | 
				
			||||||
@@ -92,27 +92,38 @@ void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename,
 | 
				
			|||||||
  sys::path::append(Path, Filename);
 | 
					  sys::path::append(Path, Filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto MachOOrError =
 | 
					  auto MachOOrError =
 | 
				
			||||||
      CurrentObjectHolder.GetFileAs<MachOObjectFile>(Path, Timestamp);
 | 
					      CurrentObjectHolder.GetFilesAs<MachOObjectFile>(Path, Timestamp);
 | 
				
			||||||
  if (auto Error = MachOOrError.getError()) {
 | 
					  if (auto Error = MachOOrError.getError()) {
 | 
				
			||||||
    Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
 | 
					    Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
 | 
				
			||||||
            Error.message() + "\n");
 | 
					            Error.message() + "\n");
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  loadCurrentObjectFileSymbols();
 | 
					  auto ErrOrAchObj =
 | 
				
			||||||
 | 
					      CurrentObjectHolder.GetAs<MachOObjectFile>(Result->getTriple());
 | 
				
			||||||
 | 
					  if (auto Err = ErrOrAchObj.getError()) {
 | 
				
			||||||
 | 
					    return Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
 | 
				
			||||||
 | 
					                   Err.message() + "\n");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CurrentDebugMapObject = &Result->addDebugMapObject(Path, Timestamp);
 | 
					  CurrentDebugMapObject = &Result->addDebugMapObject(Path, Timestamp);
 | 
				
			||||||
 | 
					  loadCurrentObjectFileSymbols(*ErrOrAchObj);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// This main parsing routine tries to open the main binary and if
 | 
					/// This main parsing routine tries to open the main binary and if
 | 
				
			||||||
/// successful iterates over the STAB entries. The real parsing is
 | 
					/// successful iterates over the STAB entries. The real parsing is
 | 
				
			||||||
/// done in handleStabSymbolTableEntry.
 | 
					/// done in handleStabSymbolTableEntry.
 | 
				
			||||||
ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
 | 
					ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
 | 
				
			||||||
  auto MainBinOrError = MainBinaryHolder.GetFileAs<MachOObjectFile>(BinaryPath);
 | 
					  auto MainBinOrError =
 | 
				
			||||||
 | 
					      MainBinaryHolder.GetFilesAs<MachOObjectFile>(BinaryPath);
 | 
				
			||||||
  if (auto Error = MainBinOrError.getError())
 | 
					  if (auto Error = MainBinOrError.getError())
 | 
				
			||||||
    return Error;
 | 
					    return Error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MachOObjectFile &MainBinary = *MainBinOrError;
 | 
					  if (MainBinOrError->size() != 1)
 | 
				
			||||||
  loadMainBinarySymbols();
 | 
					    return make_error_code(object::object_error::invalid_file_type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MachOObjectFile &MainBinary = *MainBinOrError->front();
 | 
				
			||||||
 | 
					  loadMainBinarySymbols(MainBinary);
 | 
				
			||||||
  Result = make_unique<DebugMap>(BinaryHolder::getTriple(MainBinary));
 | 
					  Result = make_unique<DebugMap>(BinaryHolder::getTriple(MainBinary));
 | 
				
			||||||
  MainBinaryStrings = MainBinary.getStringTableData();
 | 
					  MainBinaryStrings = MainBinary.getStringTableData();
 | 
				
			||||||
  for (const SymbolRef &Symbol : MainBinary.symbols()) {
 | 
					  for (const SymbolRef &Symbol : MainBinary.symbols()) {
 | 
				
			||||||
@@ -189,10 +200,11 @@ void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Load the current object file symbols into CurrentObjectAddresses.
 | 
					/// Load the current object file symbols into CurrentObjectAddresses.
 | 
				
			||||||
void MachODebugMapParser::loadCurrentObjectFileSymbols() {
 | 
					void MachODebugMapParser::loadCurrentObjectFileSymbols(
 | 
				
			||||||
 | 
					    const object::MachOObjectFile &Obj) {
 | 
				
			||||||
  CurrentObjectAddresses.clear();
 | 
					  CurrentObjectAddresses.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (auto Sym : CurrentObjectHolder.Get().symbols()) {
 | 
					  for (auto Sym : Obj.symbols()) {
 | 
				
			||||||
    uint64_t Addr = Sym.getValue();
 | 
					    uint64_t Addr = Sym.getValue();
 | 
				
			||||||
    ErrorOr<StringRef> Name = Sym.getName();
 | 
					    ErrorOr<StringRef> Name = Sym.getName();
 | 
				
			||||||
    if (!Name)
 | 
					    if (!Name)
 | 
				
			||||||
@@ -213,9 +225,10 @@ uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Load the interesting main binary symbols' addresses into
 | 
					/// Load the interesting main binary symbols' addresses into
 | 
				
			||||||
/// MainBinarySymbolAddresses.
 | 
					/// MainBinarySymbolAddresses.
 | 
				
			||||||
void MachODebugMapParser::loadMainBinarySymbols() {
 | 
					void MachODebugMapParser::loadMainBinarySymbols(
 | 
				
			||||||
  const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs<MachOObjectFile>();
 | 
					    const MachOObjectFile &MainBinary) {
 | 
				
			||||||
  section_iterator Section = MainBinary.section_end();
 | 
					  section_iterator Section = MainBinary.section_end();
 | 
				
			||||||
 | 
					  MainBinarySymbolAddresses.clear();
 | 
				
			||||||
  for (const auto &Sym : MainBinary.symbols()) {
 | 
					  for (const auto &Sym : MainBinary.symbols()) {
 | 
				
			||||||
    SymbolRef::Type Type = Sym.getType();
 | 
					    SymbolRef::Type Type = Sym.getType();
 | 
				
			||||||
    // Skip undefined and STAB entries.
 | 
					    // Skip undefined and STAB entries.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user