diff options
Diffstat (limited to 'lib/Object')
-rw-r--r-- | lib/Object/Archive.cpp | 279 | ||||
-rw-r--r-- | lib/Object/COFFObjectFile.cpp | 2 | ||||
-rw-r--r-- | lib/Object/ELFObjectFile.cpp | 46 | ||||
-rw-r--r-- | lib/Object/MachOObject.cpp | 18 | ||||
-rw-r--r-- | lib/Object/MachOObjectFile.cpp | 104 | ||||
-rw-r--r-- | lib/Object/ObjectFile.cpp | 4 |
6 files changed, 280 insertions, 173 deletions
diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index 2a5951a..0e13d05 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -21,44 +21,6 @@ using namespace object; static const char *Magic = "!<arch>\n"; -namespace { -struct ArchiveMemberHeader { - char Name[16]; - char LastModified[12]; - char UID[6]; - char GID[6]; - char AccessMode[8]; - char Size[10]; ///< Size of data, not including header or padding. - char Terminator[2]; - - ///! Get the name without looking up long names. - StringRef getName() const { - char EndCond; - if (Name[0] == '/' || Name[0] == '#') - EndCond = ' '; - else - EndCond = '/'; - StringRef::size_type end = StringRef(Name, sizeof(Name)).find(EndCond); - if (end == StringRef::npos) - end = sizeof(Name); - assert(end <= sizeof(Name) && end > 0); - // Don't include the EndCond if there is one. - return StringRef(Name, end); - } - - uint64_t getSize() const { - APInt ret; - StringRef(Size, sizeof(Size)).getAsInteger(10, ret); - return ret.getZExtValue(); - } -}; -} - -static const ArchiveMemberHeader *ToHeader(const char *base) { - return reinterpret_cast<const ArchiveMemberHeader *>(base); -} - - static bool isInternalMember(const ArchiveMemberHeader &amh) { static const char *const internals[] = { "/", @@ -76,25 +38,6 @@ static bool isInternalMember(const ArchiveMemberHeader &amh) { void Archive::anchor() { } -Archive::Child Archive::Child::getNext() const { - size_t SpaceToSkip = sizeof(ArchiveMemberHeader) + - ToHeader(Data.data())->getSize(); - // If it's odd, add 1 to make it even. - if (SpaceToSkip & 1) - ++SpaceToSkip; - - const char *NextLoc = Data.data() + SpaceToSkip; - - // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data->getBufferEnd()) - return Child(Parent, StringRef(0, 0)); - - size_t NextSize = sizeof(ArchiveMemberHeader) + - ToHeader(NextLoc)->getSize(); - - return Child(Parent, StringRef(NextLoc, NextSize)); -} - error_code Archive::Child::getName(StringRef &Result) const { StringRef name = ToHeader(Data.data())->getName(); // Check if it's a special name. @@ -109,11 +52,12 @@ error_code Archive::Child::getName(StringRef &Result) const { } // It's a long name. // Get the offset. - APInt offset; - name.substr(1).getAsInteger(10, offset); + std::size_t offset; + if (name.substr(1).rtrim(" ").getAsInteger(10, offset)) + llvm_unreachable("Long name offset is not an integer"); const char *addr = Parent->StringTable->Data.begin() + sizeof(ArchiveMemberHeader) - + offset.getZExtValue(); + + offset; // Verify it. if (Parent->StringTable == Parent->end_children() || addr < (Parent->StringTable->Data.begin() @@ -122,12 +66,20 @@ error_code Archive::Child::getName(StringRef &Result) const { + sizeof(ArchiveMemberHeader) + Parent->StringTable->getSize())) return object_error::parse_failed; - Result = addr; + + // GNU long file names end with a /. + if (Parent->kind() == K_GNU) { + StringRef::size_type End = StringRef(addr).find('/'); + Result = StringRef(addr, End); + } else { + Result = addr; + } return object_error::success; } else if (name.startswith("#1/")) { - APInt name_size; - name.substr(3).getAsInteger(10, name_size); - Result = Data.substr(0, name_size.getZExtValue()); + uint64_t name_size; + if (name.substr(3).rtrim(" ").getAsInteger(10, name_size)) + llvm_unreachable("Long name length is not an ingeter"); + Result = Data.substr(sizeof(ArchiveMemberHeader), name_size); return object_error::success; } // It's a simple name. @@ -138,36 +90,12 @@ error_code Archive::Child::getName(StringRef &Result) const { return object_error::success; } -uint64_t Archive::Child::getSize() const { - uint64_t size = ToHeader(Data.data())->getSize(); - // Don't include attached name. - StringRef name = ToHeader(Data.data())->getName(); - if (name.startswith("#1/")) { - APInt name_size; - name.substr(3).getAsInteger(10, name_size); - size -= name_size.getZExtValue(); - } - return size; -} - -MemoryBuffer *Archive::Child::getBuffer() const { - StringRef name; - if (getName(name)) return NULL; - int size = sizeof(ArchiveMemberHeader); - if (name.startswith("#1/")) { - APInt name_size; - name.substr(3).getAsInteger(10, name_size); - size += name_size.getZExtValue(); - } - return MemoryBuffer::getMemBuffer(Data.substr(size, getSize()), - name, - false); -} - error_code Archive::Child::getAsBinary(OwningPtr<Binary> &Result) const { OwningPtr<Binary> ret; - if (error_code ec = - createBinary(getBuffer(), ret)) + OwningPtr<MemoryBuffer> Buff; + if (error_code ec = getMemoryBuffer(Buff)) + return ec; + if (error_code ec = createBinary(Buff.take(), ret)) return ec; Result.swap(ret); return object_error::success; @@ -187,15 +115,56 @@ Archive::Archive(MemoryBuffer *source, error_code &ec) child_iterator i = begin_children(false); child_iterator e = end_children(); - if (i != e) ++i; // Nobody cares about the first member. - if (i != e) { - SymbolTable = i; - ++i; - } - if (i != e) { - StringTable = i; - } + StringRef name; + if ((ec = i->getName(name))) + return; + // Below is the pattern that is used to figure out the archive format + // GNU archive format + // First member : / (points to the symbol table ) + // Second member : // (may exist, if it exists, points to the string table) + // Note : The string table is used if the filename exceeds 15 characters + // BSD archive format + // First member : __.SYMDEF (points to the symbol table) + // There is no string table, if the filename exceeds 15 characters or has a + // embedded space, the filename has #1/<size>, The size represents the size + // of the filename that needs to be read after the archive header + // COFF archive format + // First member : / + // Second member : / (provides a directory of symbols) + // Third member : // contains the string table, this is present even if the + // string table is empty + if (name == "/") { + SymbolTable = i; + StringTable = e; + if (i != e) ++i; + if (i == e) { + ec = object_error::parse_failed; + return; + } + if ((ec = i->getName(name))) + return; + if (name[0] != '/') { + Format = K_GNU; + } else if ((name.size() > 1) && (name == "//")) { + Format = K_GNU; + StringTable = i; + ++i; + } else { + Format = K_COFF; + if (i != e) { + SymbolTable = i; + ++i; + } + if (i != e) { + StringTable = i; + } + } + } else if (name == "__.SYMDEF") { + Format = K_BSD; + SymbolTable = i; + StringTable = e; + } ec = object_error::success; } @@ -215,26 +184,50 @@ Archive::child_iterator Archive::end_children() const { } error_code Archive::Symbol::getName(StringRef &Result) const { - Result = - StringRef(Parent->SymbolTable->getBuffer()->getBufferStart() + StringIndex); + Result = StringRef(Parent->SymbolTable->getBuffer().begin() + StringIndex); return object_error::success; } error_code Archive::Symbol::getMember(child_iterator &Result) const { - const char *buf = Parent->SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); - const char *offsets = buf + 4; - buf += 4 + (member_count * 4); // Skip offsets. - const char *indicies = buf + 4; + const char *Buf = Parent->SymbolTable->getBuffer().begin(); + const char *Offsets = Buf + 4; + uint32_t Offset = 0; + if (Parent->kind() == K_GNU) { + Offset = *(reinterpret_cast<const support::ubig32_t*>(Offsets) + + SymbolIndex); + } else if (Parent->kind() == K_BSD) { + llvm_unreachable("BSD format is not supported"); + } else { + uint32_t MemberCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); + + // Skip offsets. + Buf += sizeof(support::ulittle32_t) + + (MemberCount * sizeof(support::ulittle32_t)); + + uint32_t SymbolCount = *reinterpret_cast<const support::ulittle32_t*>(Buf); + + if (SymbolIndex >= SymbolCount) + return object_error::parse_failed; + + // Skip SymbolCount to get to the indices table. + const char *Indices = Buf + sizeof(support::ulittle32_t); + + // Get the index of the offset in the file member offset table for this + // symbol. + uint16_t OffsetIndex = + *(reinterpret_cast<const support::ulittle16_t*>(Indices) + + SymbolIndex); + // Subtract 1 since OffsetIndex is 1 based. + --OffsetIndex; - uint16_t offsetindex = - *(reinterpret_cast<const support::ulittle16_t*>(indicies) - + SymbolIndex); + if (OffsetIndex >= MemberCount) + return object_error::parse_failed; - uint32_t offset = *(reinterpret_cast<const support::ulittle32_t*>(offsets) - + (offsetindex - 1)); + Offset = *(reinterpret_cast<const support::ulittle32_t*>(Offsets) + + OffsetIndex); + } - const char *Loc = Parent->getData().begin() + offset; + const char *Loc = Parent->getData().begin() + Offset; size_t Size = sizeof(ArchiveMemberHeader) + ToHeader(Loc)->getSize(); Result = Child(Parent, StringRef(Loc, Size)); @@ -246,27 +239,63 @@ Archive::Symbol Archive::Symbol::getNext() const { Symbol t(*this); // Go to one past next null. t.StringIndex = - Parent->SymbolTable->getBuffer()->getBuffer().find('\0', t.StringIndex) + 1; + Parent->SymbolTable->getBuffer().find('\0', t.StringIndex) + 1; ++t.SymbolIndex; return t; } Archive::symbol_iterator Archive::begin_symbols() const { - const char *buf = SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); - buf += 4 + (symbol_count * 2); // Skip indices. - uint32_t string_start_offset = - buf - SymbolTable->getBuffer()->getBufferStart(); + const char *buf = SymbolTable->getBuffer().begin(); + if (kind() == K_GNU) { + uint32_t symbol_count = 0; + symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); + buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_BSD) { + llvm_unreachable("BSD archive format is not supported"); + } else { + uint32_t member_count = 0; + uint32_t symbol_count = 0; + member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (symbol_count * 2); // Skip indices. + } + uint32_t string_start_offset = buf - SymbolTable->getBuffer().begin(); return symbol_iterator(Symbol(this, 0, string_start_offset)); } Archive::symbol_iterator Archive::end_symbols() const { - const char *buf = SymbolTable->getBuffer()->getBufferStart(); - uint32_t member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); - buf += 4 + (member_count * 4); // Skip offsets. - uint32_t symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + const char *buf = SymbolTable->getBuffer().begin(); + uint32_t symbol_count = 0; + if (kind() == K_GNU) { + symbol_count = *reinterpret_cast<const support::ubig32_t*>(buf); + buf += sizeof(uint32_t) + (symbol_count * (sizeof(uint32_t))); + } else if (kind() == K_BSD) { + llvm_unreachable("BSD archive format is not supported"); + } else { + uint32_t member_count = 0; + member_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + buf += 4 + (member_count * 4); // Skip offsets. + symbol_count = *reinterpret_cast<const support::ulittle32_t*>(buf); + } return symbol_iterator( Symbol(this, symbol_count, 0)); } + +Archive::child_iterator Archive::findSym(StringRef name) const { + Archive::symbol_iterator bs = begin_symbols(); + Archive::symbol_iterator es = end_symbols(); + Archive::child_iterator result; + + StringRef symname; + for (; bs != es; ++bs) { + if (bs->getName(symname)) + return end_children(); + if (symname == name) { + if (bs->getMember(result)) + return end_children(); + return result; + } + } + return end_children(); +} diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 0b7ee34..ca90e0e 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -267,7 +267,7 @@ error_code COFFObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, } if (symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) - ret = ::toupper(ret); + ret = ::toupper(static_cast<unsigned char>(ret)); Result = ret; return object_error::success; diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 663b84e..cfe0eb4 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/ELF.h" +#include "llvm/Support/MathExtras.h" namespace llvm { @@ -22,16 +23,49 @@ ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) { std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object); error_code ec; + std::size_t MaxAlignment = + 1ULL << CountTrailingZeros_64(uintptr_t(Object->getBufferStart())); + if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) - return new ELFObjectFile<support::little, false>(Object, ec); +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 4) + return new ELFObjectFile<ELFType<support::little, 4, false> >(Object, ec); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::little, 2, false> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, false>(Object, ec); +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 4) + return new ELFObjectFile<ELFType<support::big, 4, false> >(Object, ec); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::big, 2, false> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) - return new ELFObjectFile<support::big, true>(Object, ec); +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 8) + return new ELFObjectFile<ELFType<support::big, 8, true> >(Object, ec); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::big, 2, true> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { - ELFObjectFile<support::little, true> *result = - new ELFObjectFile<support::little, true>(Object, ec); - return result; +#if !LLVM_IS_UNALIGNED_ACCESS_FAST + if (MaxAlignment >= 8) + return new ELFObjectFile<ELFType<support::little, 8, true> >(Object, ec); + else +#endif + if (MaxAlignment >= 2) + return new ELFObjectFile<ELFType<support::little, 2, true> >(Object, ec); + else + llvm_unreachable("Invalid alignment for ELF file!"); } report_fatal_error("Buffer is not an ELF object file!"); diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp index 00dea3f..c9c341a 100644 --- a/lib/Object/MachOObject.cpp +++ b/lib/Object/MachOObject.cpp @@ -8,14 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/MachOObject.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::object; @@ -44,7 +44,8 @@ static void ReadInMemoryStruct(const MachOObject &MOO, } // Check whether we can return a direct pointer. - struct_type *Ptr = (struct_type *) (Buffer.data() + Base); + struct_type *Ptr = reinterpret_cast<struct_type *>( + const_cast<char *>(Buffer.data() + Base)); if (!MOO.isSwappedEndian()) { Res = Ptr; return; @@ -258,6 +259,17 @@ void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI, } template<> +void SwapStruct(macho::LinkerOptionsLoadCommand &Value) { + SwapValue(Value.Type); + SwapValue(Value.Size); + SwapValue(Value.Count); +} +void MachOObject::ReadLinkerOptionsLoadCommand(const LoadCommandInfo &LCI, + InMemoryStruct<macho::LinkerOptionsLoadCommand> &Res) const { + ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); +} + +template<> void SwapStruct(macho::IndirectSymbolTableEntry &Value) { SwapValue(Value.Index); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 45aeaac..6501df9 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -12,12 +12,11 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/Triple.h" #include "llvm/Object/MachO.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" - #include <cctype> #include <cstring> #include <limits> @@ -50,7 +49,15 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); if (!MachOObj) return NULL; - return new MachOObjectFile(Buffer, MachOObj, ec); + // MachOObject takes ownership of the Buffer we passed to it, and + // MachOObjectFile does, too, so we need to make sure they don't get the + // same object. A MemoryBuffer is cheap (it's just a reference to memory, + // not a copy of the memory itself), so just make a new copy here for + // the MachOObjectFile. + MemoryBuffer *NewBuffer = + MemoryBuffer::getMemBuffer(Buffer->getBuffer(), + Buffer->getBufferIdentifier(), false); + return new MachOObjectFile(NewBuffer, MachOObj, ec); } /*===-- Symbols -----------------------------------------------------------===*/ @@ -266,7 +273,7 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, } if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) - Char = toupper(Char); + Char = toupper(static_cast<unsigned char>(Char)); Result = Char; return object_error::success; } @@ -440,9 +447,7 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, void MachOObjectFile::getSection(DataRefImpl DRI, InMemoryStruct<macho::Section> &Res) const { - InMemoryStruct<macho::SegmentLoadCommand> SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSegmentLoadCommand(LCI, SLC); MachOObj->ReadSection(LCI, DRI.d.b, Res); } @@ -456,9 +461,7 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { void MachOObjectFile::getSection64(DataRefImpl DRI, InMemoryStruct<macho::Section64> &Res) const { - InMemoryStruct<macho::Segment64LoadCommand> SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSegment64LoadCommand(LCI, SLC); MachOObj->ReadSection64(LCI, DRI.d.b, Res); } @@ -470,38 +473,61 @@ static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { return false; } +static StringRef parseSegmentOrSectionName(const char *P) { + if (P[15] == 0) + // Null terminated. + return P; + // Not null terminated, so this is a 16 char string. + return StringRef(P, 16); +} + error_code MachOObjectFile::getSectionName(DataRefImpl DRI, StringRef &Result) const { - // FIXME: thread safety. - static char result[34]; - if (is64BitLoadCommand(MachOObj, DRI)) { - InMemoryStruct<macho::Segment64LoadCommand> SLC; + if (is64BitLoadCommand(MachOObj.get(), DRI)) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSegment64LoadCommand(LCI, SLC); - InMemoryStruct<macho::Section64> Sect; - MachOObj->ReadSection64(LCI, DRI.d.b, Sect); - - strcpy(result, Sect->SegmentName); - strcat(result, ","); - strcat(result, Sect->Name); + unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + + DRI.d.b * sizeof(macho::Section64); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); + const macho::Section64 *sec = + reinterpret_cast<const macho::Section64*>(Data.data()); + Result = parseSegmentOrSectionName(sec->Name); } else { - InMemoryStruct<macho::SegmentLoadCommand> SLC; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSegmentLoadCommand(LCI, SLC); - InMemoryStruct<macho::Section> Sect; - MachOObj->ReadSection(LCI, DRI.d.b, Sect); + unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + + DRI.d.b * sizeof(macho::Section); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); + const macho::Section *sec = + reinterpret_cast<const macho::Section*>(Data.data()); + Result = parseSegmentOrSectionName(sec->Name); + } + return object_error::success; +} - strcpy(result, Sect->SegmentName); - strcat(result, ","); - strcat(result, Sect->Name); +error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec, + StringRef &Res) const { + if (is64BitLoadCommand(MachOObj.get(), Sec)) { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a); + unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + + Sec.d.b * sizeof(macho::Section64); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); + const macho::Section64 *sec = + reinterpret_cast<const macho::Section64*>(Data.data()); + Res = parseSegmentOrSectionName(sec->SegmentName); + } else { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a); + unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + + Sec.d.b * sizeof(macho::Section); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); + const macho::Section *sec = + reinterpret_cast<const macho::Section*>(Data.data()); + Res = parseSegmentOrSectionName(sec->SegmentName); } - Result = StringRef(result); return object_error::success; } error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj, DRI)) { + if (is64BitLoadCommand(MachOObj.get(), DRI)) { InMemoryStruct<macho::Section64> Sect; getSection64(DRI, Sect); Result = Sect->Address; @@ -515,7 +541,7 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj, DRI)) { + if (is64BitLoadCommand(MachOObj.get(), DRI)) { InMemoryStruct<macho::Section64> Sect; getSection64(DRI, Sect); Result = Sect->Size; @@ -529,7 +555,7 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { - if (is64BitLoadCommand(MachOObj, DRI)) { + if (is64BitLoadCommand(MachOObj.get(), DRI)) { InMemoryStruct<macho::Section64> Sect; getSection64(DRI, Sect); Result = MachOObj->getData(Sect->Offset, Sect->Size); @@ -543,7 +569,7 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj, DRI)) { + if (is64BitLoadCommand(MachOObj.get(), DRI)) { InMemoryStruct<macho::Section64> Sect; getSection64(DRI, Sect); Result = uint64_t(1) << Sect->Align; @@ -557,14 +583,14 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { - if (is64BitLoadCommand(MachOObj, DRI)) { + if (is64BitLoadCommand(MachOObj.get(), DRI)) { InMemoryStruct<macho::Section64> Sect; getSection64(DRI, Sect); - Result = !strcmp(Sect->Name, "__text"); + Result = Sect->Flags & macho::SF_PureInstructions; } else { InMemoryStruct<macho::Section> Sect; getSection(DRI, Sect); - Result = !strcmp(Sect->Name, "__text"); + Result = Sect->Flags & macho::SF_PureInstructions; } return object_error::success; } @@ -664,7 +690,7 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; - if (is64BitLoadCommand(MachOObj, Sec)) { + if (is64BitLoadCommand(MachOObj.get(), Sec)) { InMemoryStruct<macho::Section64> Sect; getSection64(Sec, Sect); last_reloc = Sect->NumRelocationTableEntries; @@ -1050,6 +1076,7 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, printRelocationTargetName(RENext, fmt); fmt << "-"; printRelocationTargetName(RE, fmt); + break; } case macho::RIT_X86_64_TLV: printRelocationTargetName(RE, fmt); @@ -1277,14 +1304,17 @@ StringRef MachOObjectFile::getFileFormatName() const { } } + // Make sure the cpu type has the correct mask. + assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) + == llvm::MachO::CPUArchABI64 && + "32-bit object file when we're 64-bit?"); + switch (MachOObj->getHeader().CPUType) { case llvm::MachO::CPUTypeX86_64: return "Mach-O 64-bit x86-64"; case llvm::MachO::CPUTypePowerPC64: return "Mach-O 64-bit ppc64"; default: - assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 1 && - "32-bit object file when we're 64-bit?"); return "Mach-O 64-bit unknown"; } } diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index b14df9a..860c87b 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -33,6 +33,8 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { sys::LLVMFileType type = sys::IdentifyFileType(Object->getBufferStart(), static_cast<unsigned>(Object->getBufferSize())); switch (type) { + case sys::Unknown_FileType: + return 0; case sys::ELF_Relocatable_FileType: case sys::ELF_Executable_FileType: case sys::ELF_SharedObject_FileType: @@ -52,7 +54,7 @@ ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { case sys::COFF_FileType: return createCOFFObjectFile(Object); default: - llvm_unreachable("Unknown Object File Type"); + llvm_unreachable("Unexpected Object File Type"); } } |