From b3e6b04aea9d12183b97770f7b250622e78fe7f1 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Thu, 28 Feb 2013 20:26:17 +0000 Subject: Move an assert earlier in a file and check that the result of our bitwise compare is equal to the field we're looking for. Noticed on inspection. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@176296 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index eb1690e659..6501df9fb9 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -1304,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"; } } -- cgit v1.2.3-70-g09d2 From f16c2bb320f4d5b33dfaf8df8865f547e6d66005 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 5 Apr 2013 15:15:22 +0000 Subject: Don't fetch pointers from a InMemoryStruct. InMemoryStruct is extremely dangerous as it returns data from an internal buffer when the endiannes doesn't match. This should fix the tests on big endian hosts. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178875 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 8 +++++++- lib/Object/MachOObjectFile.cpp | 27 ++++++++++++++++++--------- test/tools/llvm-readobj/sections-ext.test | 4 ++-- test/tools/llvm-readobj/sections.test | 8 ++++---- tools/llvm-objdump/MachODump.cpp | 5 ++--- tools/llvm-objdump/llvm-objdump.cpp | 7 ++----- tools/llvm-readobj/MachODumper.cpp | 23 ++++++++--------------- 7 files changed, 43 insertions(+), 39 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index ed7aabd2c8..83e9c013ca 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -15,6 +15,7 @@ #ifndef LLVM_OBJECT_MACHO_H #define LLVM_OBJECT_MACHO_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Object/MachOObject.h" #include "llvm/Object/ObjectFile.h" @@ -47,7 +48,12 @@ public: // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment // a section should be put in in the final object. - error_code getSectionFinalSegmentName(DataRefImpl Sec, StringRef &Res) const; + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef getSectionRawName(DataRefImpl Sec) const; + ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; MachOObject *getObject() { return MachOObj.get(); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 6501df9fb9..9ab3599e2d 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -481,8 +481,7 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -error_code MachOObjectFile::getSectionName(DataRefImpl DRI, - StringRef &Result) const { +ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + @@ -490,7 +489,7 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); const macho::Section64 *sec = reinterpret_cast(Data.data()); - Result = parseSegmentOrSectionName(sec->Name); + return ArrayRef(sec->Name, 16); } else { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + @@ -498,13 +497,19 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); const macho::Section *sec = reinterpret_cast(Data.data()); - Result = parseSegmentOrSectionName(sec->Name); + return ArrayRef(sec->Name, 16); } +} + +error_code MachOObjectFile::getSectionName(DataRefImpl DRI, + StringRef &Result) const { + ArrayRef Raw = getSectionRawName(DRI); + Result = parseSegmentOrSectionName(Raw.data()); return object_error::success; } -error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec, - StringRef &Res) const { +ArrayRef +MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { if (is64BitLoadCommand(MachOObj.get(), Sec)) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + @@ -512,7 +517,7 @@ error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec, StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); const macho::Section64 *sec = reinterpret_cast(Data.data()); - Res = parseSegmentOrSectionName(sec->SegmentName); + return ArrayRef(sec->SegmentName, 16); } else { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(Sec.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + @@ -520,9 +525,13 @@ error_code MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec, StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); const macho::Section *sec = reinterpret_cast(Data.data()); - Res = parseSegmentOrSectionName(sec->SegmentName); + return ArrayRef(sec->SegmentName); } - return object_error::success; +} + +StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { + ArrayRef Raw = getSectionRawFinalSegmentName(DRI); + return parseSegmentOrSectionName(Raw.data()); } error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index 3254040c05..a972c9ab51 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -135,8 +135,8 @@ ELF-NEXT: } MACHO: Sections [ MACHO-NEXT: Section { MACHO-NEXT: Index: 0 -MACHO-NEXT: Name: __text (5F 5F 74 65 78 74 00 -MACHO-NEXT: Segment: +MACHO-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) MACHO-NEXT: Address: 0x0 MACHO-NEXT: Size: 0x22 MACHO-NEXT: Offset: 324 diff --git a/test/tools/llvm-readobj/sections.test b/test/tools/llvm-readobj/sections.test index e5c6c063b2..84154d759c 100644 --- a/test/tools/llvm-readobj/sections.test +++ b/test/tools/llvm-readobj/sections.test @@ -79,8 +79,8 @@ ELF-NEXT: } MACHO: Sections [ MACHO-NEXT: Section { MACHO-NEXT: Index: 0 -MACHO-NEXT: Name: __text ( -MACHO-NEXT: Segment: +MACHO-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) MACHO-NEXT: Address: 0x0 MACHO-NEXT: Size: 0x22 MACHO-NEXT: Offset: 324 @@ -97,8 +97,8 @@ MACHO-NEXT: Reserved2: 0x0 MACHO-NEXT: } MACHO-NEXT: Section { MACHO-NEXT: Index: 1 -MACHO-NEXT: Name: __cstring ( -MACHO-NEXT: Segment: +MACHO-NEXT: Name: __cstring (5F 5F 63 73 74 72 69 6E 67 00 00 00 00 00 00 00) +MACHO-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) MACHO-NEXT: Address: 0x22 MACHO-NEXT: Size: 0xD MACHO-NEXT: Offset: 358 diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index c324ff13a6..e9d2b3b1a8 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -337,10 +337,9 @@ void llvm::DisassembleInputMachO(StringRef Filename) { SectName != "__text") continue; // Skip non-text sections - StringRef SegmentName; DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl(); - if (MachOOF->getSectionFinalSegmentName(DR, SegmentName) || - SegmentName != "__TEXT") + StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR); + if (SegmentName != "__TEXT") continue; // Insert the functions from the function starts segment into our map. diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 7832cf0dff..9a36e8253d 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -257,8 +257,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { StringRef SegmentName = ""; if (const MachOObjectFile *MachO = dyn_cast(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); - if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) - break; + SegmentName = MachO->getSectionFinalSegmentName(DR); } StringRef name; if (error(i->getName(name))) break; @@ -593,10 +592,8 @@ static void PrintSymbolTable(const ObjectFile *o) { outs() << "*UND*"; else { if (const MachOObjectFile *MachO = dyn_cast(o)) { - StringRef SegmentName; DataRefImpl DR = Section->getRawDataRefImpl(); - if (error(MachO->getSectionFinalSegmentName(DR, SegmentName))) - SegmentName = ""; + StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); outs() << SegmentName << ","; } StringRef SectionName; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 798c941772..0354e767ba 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -157,14 +157,6 @@ namespace { }; } -static StringRef parseSegmentOrSectionName(ArrayRef P) { - if (P[15] == 0) - // Null terminated. - return StringRef(P.data()); - // Not null terminated, so this is a 16 char string. - return StringRef(P.data(), 16); -} - static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Segment64) @@ -181,8 +173,6 @@ static void getSection(const MachOObject *MachOObj, InMemoryStruct Sect; MachOObj->ReadSection64(LCI, DRI.d.b, Sect); - Section.Name = ArrayRef(Sect->Name); - Section.SegmentName = ArrayRef(Sect->SegmentName); Section.Address = Sect->Address; Section.Size = Sect->Size; Section.Offset = Sect->Offset; @@ -196,8 +186,6 @@ static void getSection(const MachOObject *MachOObj, InMemoryStruct Sect; MachOObj->ReadSection(LCI, DRI.d.b, Sect); - Section.Name = Sect->Name; - Section.SegmentName = Sect->SegmentName; Section.Address = Sect->Address; Section.Size = Sect->Size; Section.Offset = Sect->Offset; @@ -270,15 +258,20 @@ void MachODumper::printSections() { MachOSection Section; getSection(MachO, SecI->getRawDataRefImpl(), Section); + DataRefImpl DR = SecI->getRawDataRefImpl(); + StringRef Name; if (error(SecI->getName(Name))) Name = ""; + ArrayRef RawName = Obj->getSectionRawName(DR); + StringRef SegmentName = Obj->getSectionFinalSegmentName(DR); + ArrayRef RawSegmentName = Obj->getSectionRawFinalSegmentName(DR); + DictScope SectionD(W, "Section"); W.printNumber("Index", SectionIndex); - W.printBinary("Name", Name, Section.Name); - W.printBinary("Segment", parseSegmentOrSectionName(Section.SegmentName), - Section.SegmentName); + W.printBinary("Name", Name, RawName); + W.printBinary("Segment", SegmentName, RawSegmentName); W.printHex ("Address", Section.Address); W.printHex ("Size", Section.Size); W.printNumber("Offset", Section.Offset); -- cgit v1.2.3-70-g09d2 From c1cd6aa7a485933fa1b451c8df899ae78382b391 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 5 Apr 2013 18:18:19 +0000 Subject: Don't use InMemoryStruct in getSection and getSection64. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178894 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 5 +- lib/Object/MachOObjectFile.cpp | 137 +++++++++++++++-------------------------- 2 files changed, 53 insertions(+), 89 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 83e9c013ca..b5aa539a7e 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -127,9 +127,8 @@ private: void getSymbol64TableEntry(DataRefImpl DRI, InMemoryStruct &Res) const; void moveToNextSymbol(DataRefImpl &DRI) const; - void getSection(DataRefImpl DRI, InMemoryStruct &Res) const; - void getSection64(DataRefImpl DRI, - InMemoryStruct &Res) const; + const macho::Section *getSection(DataRefImpl DRI) const; + const macho::Section64 *getSection64(DataRefImpl DRI) const; void getRelocation(DataRefImpl Rel, InMemoryStruct &Res) const; std::size_t getSectionIndex(DataRefImpl Sec) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 9ab3599e2d..684a43b48b 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -138,8 +138,8 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, getSymbol64TableEntry(DRI, Entry); Result = Entry->Value; if (Entry->SectionIndex) { - InMemoryStruct Section; - getSection64(Sections[Entry->SectionIndex-1], Section); + const macho::Section64 *Section = + getSection64(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } } else { @@ -147,8 +147,8 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, getSymbolTableEntry(DRI, Entry); Result = Entry->Value; if (Entry->SectionIndex) { - InMemoryStruct Section; - getSection(Sections[Entry->SectionIndex-1], Section); + const macho::Section *Section = + getSection(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } } @@ -444,11 +444,21 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, return object_error::success; } -void -MachOObjectFile::getSection(DataRefImpl DRI, - InMemoryStruct &Res) const { +static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSection(LCI, DRI.d.b, Res); + if (LCI.Command.Type == macho::LCT_Segment64) + return true; + assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); + return false; +} + +const macho::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { + assert(!is64BitLoadCommand(MachOObj.get(), DRI)); + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + + DRI.d.b * sizeof(macho::Section); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); + return reinterpret_cast(Data.data()); } std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { @@ -458,19 +468,14 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -void -MachOObjectFile::getSection64(DataRefImpl DRI, - InMemoryStruct &Res) const { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSection64(LCI, DRI.d.b, Res); -} - -static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { +const macho::Section64 * +MachOObjectFile::getSection64(DataRefImpl DRI) const { + assert(is64BitLoadCommand(MachOObj.get(), DRI)); LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Segment64) - return true; - assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); - return false; + unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + + DRI.d.b * sizeof(macho::Section64); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); + return reinterpret_cast(Data.data()); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -483,21 +488,11 @@ static StringRef parseSegmentOrSectionName(const char *P) { ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - 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(Data.data()); - return ArrayRef(sec->Name, 16); + const macho::Section64 *sec = getSection64(DRI); + return ArrayRef(sec->Name); } else { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - 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(Data.data()); - return ArrayRef(sec->Name, 16); + const macho::Section *sec = getSection(DRI); + return ArrayRef(sec->Name); } } @@ -511,20 +506,10 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) 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(Data.data()); + const macho::Section64 *sec = getSection64(Sec); return ArrayRef(sec->SegmentName, 16); } 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(Data.data()); + const macho::Section *sec = getSection(Sec); return ArrayRef(sec->SegmentName); } } @@ -537,12 +522,10 @@ StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); Result = Sect->Address; } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); Result = Sect->Address; } return object_error::success; @@ -551,12 +534,10 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); Result = Sect->Size; } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); Result = Sect->Size; } return object_error::success; @@ -565,12 +546,10 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); Result = MachOObj->getData(Sect->Offset, Sect->Size); } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); Result = MachOObj->getData(Sect->Offset, Sect->Size); } return object_error::success; @@ -579,12 +558,10 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); Result = uint64_t(1) << Sect->Align; } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); Result = uint64_t(1) << Sect->Align; } return object_error::success; @@ -593,12 +570,10 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } return object_error::success; @@ -635,14 +610,12 @@ error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, bool &Result) const { if (MachOObj->is64Bit()) { - InMemoryStruct Sect; - getSection64(DRI, Sect); + const macho::Section64 *Sect = getSection64(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); } else { - InMemoryStruct Sect; - getSection(DRI, Sect); + const macho::Section *Sect = getSection(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); @@ -700,12 +673,10 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; if (is64BitLoadCommand(MachOObj.get(), Sec)) { - InMemoryStruct Sect; - getSection64(Sec, Sect); + const macho::Section64 *Sect = getSection64(Sec); last_reloc = Sect->NumRelocationTableEntries; } else { - InMemoryStruct Sect; - getSection(Sec, Sect); + const macho::Section *Sect = getSection(Sec); last_reloc = Sect->NumRelocationTableEntries; } DataRefImpl ret; @@ -733,12 +704,10 @@ getRelocation(DataRefImpl Rel, InMemoryStruct &Res) const { uint32_t relOffset; if (MachOObj->is64Bit()) { - InMemoryStruct Sect; - getSection64(Sections[Rel.d.b], Sect); + const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } else { - InMemoryStruct Sect; - getSection(Sections[Rel.d.b], Sect); + const macho::Section *Sect = getSection(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); @@ -753,12 +722,10 @@ error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { const uint8_t* sectAddress = 0; if (MachOObj->is64Bit()) { - InMemoryStruct Sect; - getSection64(Sections[Rel.d.b], Sect); + const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Address; } else { - InMemoryStruct Sect; - getSection(Sections[Rel.d.b], Sect); + const macho::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Address; } InMemoryStruct RE; @@ -928,12 +895,10 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, if (!isExtern) { const uint8_t* sectAddress = base(); if (MachOObj->is64Bit()) { - InMemoryStruct Sect; - getSection64(Sections[Rel.d.b], Sect); + const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Offset; } else { - InMemoryStruct Sect; - getSection(Sections[Rel.d.b], Sect); + const macho::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Offset; } Res = reinterpret_cast(sectAddress); -- cgit v1.2.3-70-g09d2 From 0e5dc8aacb548d51b0ca9035a7d449a8e5862dd2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 5 Apr 2013 18:45:28 +0000 Subject: Define versions of Section that are explicitly marked as little endian. These should really be templated like ELF, but this is a start. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178896 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 36 ++++++++++++++++++++-- lib/Object/MachOObjectFile.cpp | 68 +++++++++++++++++++++--------------------- 2 files changed, 68 insertions(+), 36 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index b5aa539a7e..badd4401e7 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -19,12 +19,44 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Object/MachOObject.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { +namespace MachOFormat { + struct Section { + char Name[16]; + char SegmentName[16]; + support::ulittle32_t Address; + support::ulittle32_t Size; + support::ulittle32_t Offset; + support::ulittle32_t Align; + support::ulittle32_t RelocationTableOffset; + support::ulittle32_t NumRelocationTableEntries; + support::ulittle32_t Flags; + support::ulittle32_t Reserved1; + support::ulittle32_t Reserved2; + }; + + struct Section64 { + char Name[16]; + char SegmentName[16]; + support::ulittle64_t Address; + support::ulittle64_t Size; + support::ulittle32_t Offset; + support::ulittle32_t Align; + support::ulittle32_t RelocationTableOffset; + support::ulittle32_t NumRelocationTableEntries; + support::ulittle32_t Flags; + support::ulittle32_t Reserved1; + support::ulittle32_t Reserved2; + support::ulittle32_t Reserved3; + }; +} + typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { @@ -127,8 +159,8 @@ private: void getSymbol64TableEntry(DataRefImpl DRI, InMemoryStruct &Res) const; void moveToNextSymbol(DataRefImpl &DRI) const; - const macho::Section *getSection(DataRefImpl DRI) const; - const macho::Section64 *getSection64(DataRefImpl DRI) const; + const MachOFormat::Section *getSection(DataRefImpl DRI) const; + const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; void getRelocation(DataRefImpl Rel, InMemoryStruct &Res) const; std::size_t getSectionIndex(DataRefImpl Sec) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 684a43b48b..7de5462dd3 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -138,7 +138,7 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, getSymbol64TableEntry(DRI, Entry); Result = Entry->Value; if (Entry->SectionIndex) { - const macho::Section64 *Section = + const MachOFormat::Section64 *Section = getSection64(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } @@ -147,7 +147,7 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, getSymbolTableEntry(DRI, Entry); Result = Entry->Value; if (Entry->SectionIndex) { - const macho::Section *Section = + const MachOFormat::Section *Section = getSection(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } @@ -452,13 +452,13 @@ static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { return false; } -const macho::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { +const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { assert(!is64BitLoadCommand(MachOObj.get(), DRI)); LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + - DRI.d.b * sizeof(macho::Section); - StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section)); - return reinterpret_cast(Data.data()); + DRI.d.b * sizeof(MachOFormat::Section); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section)); + return reinterpret_cast(Data.data()); } std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { @@ -468,14 +468,14 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -const macho::Section64 * +const MachOFormat::Section64 * MachOObjectFile::getSection64(DataRefImpl DRI) const { assert(is64BitLoadCommand(MachOObj.get(), DRI)); LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + - DRI.d.b * sizeof(macho::Section64); - StringRef Data = MachOObj->getData(SectionOffset, sizeof(macho::Section64)); - return reinterpret_cast(Data.data()); + DRI.d.b * sizeof(MachOFormat::Section64); + StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64)); + return reinterpret_cast(Data.data()); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -488,10 +488,10 @@ static StringRef parseSegmentOrSectionName(const char *P) { ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *sec = getSection64(DRI); + const MachOFormat::Section64 *sec = getSection64(DRI); return ArrayRef(sec->Name); } else { - const macho::Section *sec = getSection(DRI); + const MachOFormat::Section *sec = getSection(DRI); return ArrayRef(sec->Name); } } @@ -506,10 +506,10 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { if (is64BitLoadCommand(MachOObj.get(), Sec)) { - const macho::Section64 *sec = getSection64(Sec); + const MachOFormat::Section64 *sec = getSection64(Sec); return ArrayRef(sec->SegmentName, 16); } else { - const macho::Section *sec = getSection(Sec); + const MachOFormat::Section *sec = getSection(Sec); return ArrayRef(sec->SegmentName); } } @@ -522,10 +522,10 @@ StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Address; } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Address; } return object_error::success; @@ -534,10 +534,10 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Size; } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Size; } return object_error::success; @@ -546,10 +546,10 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); Result = MachOObj->getData(Sect->Offset, Sect->Size); } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = MachOObj->getData(Sect->Offset, Sect->Size); } return object_error::success; @@ -558,10 +558,10 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); Result = uint64_t(1) << Sect->Align; } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = uint64_t(1) << Sect->Align; } return object_error::success; @@ -570,10 +570,10 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { if (is64BitLoadCommand(MachOObj.get(), DRI)) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } return object_error::success; @@ -610,12 +610,12 @@ error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, bool &Result) const { if (MachOObj->is64Bit()) { - const macho::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section64 *Sect = getSection64(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); } else { - const macho::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); @@ -673,10 +673,10 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; if (is64BitLoadCommand(MachOObj.get(), Sec)) { - const macho::Section64 *Sect = getSection64(Sec); + const MachOFormat::Section64 *Sect = getSection64(Sec); last_reloc = Sect->NumRelocationTableEntries; } else { - const macho::Section *Sect = getSection(Sec); + const MachOFormat::Section *Sect = getSection(Sec); last_reloc = Sect->NumRelocationTableEntries; } DataRefImpl ret; @@ -704,10 +704,10 @@ getRelocation(DataRefImpl Rel, InMemoryStruct &Res) const { uint32_t relOffset; if (MachOObj->is64Bit()) { - const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } else { - const macho::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); @@ -722,10 +722,10 @@ error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { const uint8_t* sectAddress = 0; if (MachOObj->is64Bit()) { - const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Address; } else { - const macho::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Address; } InMemoryStruct RE; @@ -895,10 +895,10 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, if (!isExtern) { const uint8_t* sectAddress = base(); if (MachOObj->is64Bit()) { - const macho::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Offset; } else { - const macho::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Offset; } Res = reinterpret_cast(sectAddress); -- cgit v1.2.3-70-g09d2 From 5cf0f51ae6530751eeeccefa55c87f1d3422d0ae Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 6 Apr 2013 01:24:11 +0000 Subject: Don't use InMemoryStruct in getRelocation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178943 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 10 +++++--- lib/Object/MachOObjectFile.cpp | 52 +++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 34 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index badd4401e7..668b5a6b21 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -55,6 +55,11 @@ namespace MachOFormat { support::ulittle32_t Reserved2; support::ulittle32_t Reserved3; }; + + struct RelocationEntry { + support::ulittle32_t Word0; + support::ulittle32_t Word1; + }; } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -161,11 +166,10 @@ private: void moveToNextSymbol(DataRefImpl &DRI) const; const MachOFormat::Section *getSection(DataRefImpl DRI) const; const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; - void getRelocation(DataRefImpl Rel, - InMemoryStruct &Res) const; + const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; std::size_t getSectionIndex(DataRefImpl Sec) const; - void printRelocationTargetName(InMemoryStruct& RE, + void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, raw_string_ostream &fmt) const; }; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 7de5462dd3..b7255d3e40 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -699,9 +699,8 @@ section_iterator MachOObjectFile::end_sections() const { /*===-- Relocations -------------------------------------------------------===*/ -void MachOObjectFile:: -getRelocation(DataRefImpl Rel, - InMemoryStruct &Res) const { +const MachOFormat::RelocationEntry * +MachOObjectFile::getRelocation(DataRefImpl Rel) const { uint32_t relOffset; if (MachOObj->is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); @@ -710,8 +709,12 @@ getRelocation(DataRefImpl Rel, const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } - MachOObj->ReadRelocationEntry(relOffset, Rel.d.a, Res); + uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); + StringRef Data = + MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry)); + return reinterpret_cast(Data.data()); } + error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const { ++Rel.d.a; @@ -728,8 +731,7 @@ error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Address; } - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -745,8 +747,7 @@ error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -759,8 +760,7 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); uint32_t SymbolIdx = RE->Word1 & 0xffffff; bool isExtern = (RE->Word1 >> 27) & 1; @@ -779,8 +779,7 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); Res = RE->Word0; Res <<= 32; Res |= RE->Word1; @@ -790,8 +789,7 @@ error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const { // TODO: Support scattered relocations. StringRef res; - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -888,8 +886,7 @@ error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, int64_t &Res) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); bool isExtern = (RE->Word1 >> 27) & 1; Res = 0; if (!isExtern) { @@ -923,7 +920,7 @@ void advanceTo(T &it, size_t Val) { } void MachOObjectFile::printRelocationTargetName( - InMemoryStruct& RE, + const MachOFormat::RelocationEntry *RE, raw_string_ostream &fmt) const { unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -994,8 +991,7 @@ void MachOObjectFile::printRelocationTargetName( error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -1032,10 +1028,9 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, break; } case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR - InMemoryStruct RENext; DataRefImpl RelNext = Rel; RelNext.d.a++; - getRelocation(RelNext, RENext); + const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); // X86_64_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. @@ -1080,10 +1075,9 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info return object_error::success; case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF - InMemoryStruct RENext; DataRefImpl RelNext = Rel; RelNext.d.a++; - getRelocation(RelNext, RENext); + const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. @@ -1110,10 +1104,9 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // handled in the generic code. switch (Type) { case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF - InMemoryStruct RENext; DataRefImpl RelNext = Rel; RelNext.d.a++; - getRelocation(RelNext, RENext); + const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. @@ -1160,10 +1153,9 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, fmt << ":lower16:("; printRelocationTargetName(RE, fmt); - InMemoryStruct RENext; DataRefImpl RelNext = Rel; RelNext.d.a++; - getRelocation(RelNext, RENext); + const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); // ARM half relocs must be followed by a relocation of type // ARM_RELOC_PAIR. @@ -1209,8 +1201,7 @@ error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { - InMemoryStruct RE; - getRelocation(Rel, RE); + const MachOFormat::RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && @@ -1233,8 +1224,7 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { DataRefImpl RelPrev = Rel; RelPrev.d.a--; - InMemoryStruct REPrev; - getRelocation(RelPrev, REPrev); + const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev); unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; -- cgit v1.2.3-70-g09d2 From 00555c13be54b7933cf5a68b50f8a7494bcd5777 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 6 Apr 2013 01:59:05 +0000 Subject: Don't use InMemoryStruct in getSymbolTableEntry. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178945 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 13 +++++++++++-- lib/Object/MachOObjectFile.cpp | 42 +++++++++++++++++++----------------------- 2 files changed, 30 insertions(+), 25 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 668b5a6b21..70d7f6ee8a 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -60,6 +60,15 @@ namespace MachOFormat { support::ulittle32_t Word0; support::ulittle32_t Word1; }; + + struct SymbolTableEntry { + support::ulittle32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + support::ulittle16_t Flags; + support::ulittle32_t Value; + }; + } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -159,8 +168,8 @@ private: void moveToNextSection(DataRefImpl &DRI) const; - void getSymbolTableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const; + const MachOFormat::SymbolTableEntry * + getSymbolTableEntry(DataRefImpl DRI) const; void getSymbol64TableEntry(DataRefImpl DRI, InMemoryStruct &Res) const; void moveToNextSymbol(DataRefImpl &DRI) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index b7255d3e40..f82ed08250 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -78,8 +78,8 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { } } -void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const { +const MachOFormat::SymbolTableEntry * +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { InMemoryStruct SymtabLoadCmd; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); @@ -89,8 +89,13 @@ void MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, RegisteredStringTable = DRI.d.a; } - MachOObj->ReadSymbolTableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, - Res); + uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; + unsigned Index = DRI.d.b; + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::SymbolTableEntry)); + StringRef Data = MachOObj->getData(Offset, + sizeof(MachOFormat::SymbolTableEntry)); + return reinterpret_cast(Data.data()); } void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, @@ -124,8 +129,7 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, getSymbol64TableEntry(DRI, Entry); Result = MachOObj->getStringAtIndex(Entry->StringIndex); } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); Result = MachOObj->getStringAtIndex(Entry->StringIndex); } return object_error::success; @@ -143,8 +147,7 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, Result += Section->Offset - Section->Address; } } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); Result = Entry->Value; if (Entry->SectionIndex) { const MachOFormat::Section *Section = @@ -163,8 +166,7 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, getSymbol64TableEntry(DRI, Entry); Result = Entry->Value; } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); Result = Entry->Value; } return object_error::success; @@ -205,8 +207,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, DRI.d.b++; } } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { @@ -225,7 +226,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, while (Command == DRI.d.a) { moveToNextSymbol(DRI); if (DRI.d.a < LoadCommandCount) { - getSymbolTableEntry(DRI, Entry); + Entry = getSymbolTableEntry(DRI); if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) if (!EndOffset || Entry->Value < EndOffset) EndOffset = Entry->Value; @@ -252,8 +253,7 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, Type = Entry->Type; Flags = Entry->Flags; } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); Type = Entry->Type; Flags = Entry->Flags; } @@ -288,8 +288,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, MachOFlags = Entry->Flags; MachOType = Entry->Type; } else { - InMemoryStruct Entry; - getSymbolTableEntry(DRI, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); MachOFlags = Entry->Flags; MachOType = Entry->Type; } @@ -326,8 +325,7 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, getSymbol64TableEntry(Symb, Entry); index = Entry->SectionIndex; } else { - InMemoryStruct Entry; - getSymbolTableEntry(Symb, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); index = Entry->SectionIndex; } @@ -347,8 +345,7 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, getSymbol64TableEntry(Symb, Entry); n_type = Entry->Type; } else { - InMemoryStruct Entry; - getSymbolTableEntry(Symb, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); n_type = Entry->Type; } Res = SymbolRef::ST_Other; @@ -656,8 +653,7 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } else { - InMemoryStruct Entry; - getSymbolTableEntry(Symb, Entry); + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } -- cgit v1.2.3-70-g09d2 From 05b5bdd024d07e7a62f1cdc39f465e10ce5dbc6d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 6 Apr 2013 02:15:44 +0000 Subject: Don't use InMemoryStruct in getSymbol64TableEntry. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178946 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 11 +++++++++-- lib/Object/MachOObjectFile.cpp | 43 +++++++++++++++++++----------------------- 2 files changed, 28 insertions(+), 26 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 70d7f6ee8a..1da9a912d3 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -69,6 +69,13 @@ namespace MachOFormat { support::ulittle32_t Value; }; + struct Symbol64TableEntry { + support::ulittle32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + support::ulittle16_t Flags; + support::ulittle64_t Value; + }; } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -170,8 +177,8 @@ private: void moveToNextSection(DataRefImpl &DRI) const; const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; - void getSymbol64TableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const; + const MachOFormat::Symbol64TableEntry * + getSymbol64TableEntry(DataRefImpl DRI) const; void moveToNextSymbol(DataRefImpl &DRI) const; const MachOFormat::Section *getSection(DataRefImpl DRI) const; const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index f82ed08250..4d9186490f 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -98,8 +98,8 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { return reinterpret_cast(Data.data()); } -void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, - InMemoryStruct &Res) const { +const MachOFormat::Symbol64TableEntry* +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { InMemoryStruct SymtabLoadCmd; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); @@ -109,11 +109,15 @@ void MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, RegisteredStringTable = DRI.d.a; } - MachOObj->ReadSymbol64TableEntry(SymtabLoadCmd->SymbolTableOffset, DRI.d.b, - Res); + uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; + unsigned Index = DRI.d.b; + uint64_t Offset = (SymbolTableOffset + + Index * sizeof(macho::Symbol64TableEntry)); + StringRef Data = MachOObj->getData(Offset, + sizeof(MachOFormat::Symbol64TableEntry)); + return reinterpret_cast(Data.data()); } - error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, SymbolRef &Result) const { DRI.d.b++; @@ -125,8 +129,7 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, StringRef &Result) const { if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Result = MachOObj->getStringAtIndex(Entry->StringIndex); } else { const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); @@ -138,8 +141,7 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, uint64_t &Result) const { if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Result = Entry->Value; if (Entry->SectionIndex) { const MachOFormat::Section64 *Section = @@ -162,8 +164,7 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, uint64_t &Result) const { if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Result = Entry->Value; } else { const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); @@ -179,8 +180,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t EndOffset = 0; uint8_t SectionIndex; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { @@ -199,7 +199,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, while (Command == DRI.d.a) { moveToNextSymbol(DRI); if (DRI.d.a < LoadCommandCount) { - getSymbol64TableEntry(DRI, Entry); + Entry = getSymbol64TableEntry(DRI); if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) if (!EndOffset || Entry->Value < EndOffset) EndOffset = Entry->Value; @@ -248,8 +248,7 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, char &Result) const { uint8_t Type, Flags; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Type = Entry->Type; Flags = Entry->Flags; } else { @@ -283,8 +282,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, uint16_t MachOFlags; uint8_t MachOType; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(DRI, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); MachOFlags = Entry->Flags; MachOType = Entry->Type; } else { @@ -321,8 +319,7 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { uint8_t index; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(Symb, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); index = Entry->SectionIndex; } else { const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); @@ -341,8 +338,7 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const { uint8_t n_type; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(Symb, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); n_type = Entry->Type; } else { const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); @@ -648,8 +644,7 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, SectEnd += SectBegin; if (MachOObj->is64Bit()) { - InMemoryStruct Entry; - getSymbol64TableEntry(Symb, Entry); + const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } else { -- cgit v1.2.3-70-g09d2 From 82a21077a004087a87711bfd7a4ab171cebaa5ec Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 6 Apr 2013 03:31:08 +0000 Subject: Don't use InMemoryStruct. This also required not using the RegisterStringTable API, which is also a good thing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178947 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 23 ++++++++++++++- lib/Object/MachOObjectFile.cpp | 63 ++++++++++++++++++++++++++++-------------- 2 files changed, 65 insertions(+), 21 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 1da9a912d3..d6abaf1be2 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -76,6 +76,15 @@ namespace MachOFormat { support::ulittle16_t Flags; support::ulittle64_t Value; }; + + struct SymtabLoadCommand { + support::ulittle32_t Type; + support::ulittle32_t Size; + support::ulittle32_t SymbolTableOffset; + support::ulittle32_t NumSymbolTableEntries; + support::ulittle32_t StringTableOffset; + support::ulittle32_t StringTableSize; + }; } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -169,20 +178,32 @@ protected: private: OwningPtr MachOObj; - mutable uint32_t RegisteredStringTable; typedef SmallVector SectionList; SectionList Sections; void moveToNextSection(DataRefImpl &DRI) const; + const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; + + const MachOFormat::SymbolTableEntry * + getSymbolTableEntry(DataRefImpl DRI, + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; + const MachOFormat::Symbol64TableEntry * getSymbol64TableEntry(DataRefImpl DRI) const; + + const MachOFormat::Symbol64TableEntry * + getSymbol64TableEntry(DataRefImpl DRI, + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; + void moveToNextSymbol(DataRefImpl &DRI) const; const MachOFormat::Section *getSection(DataRefImpl DRI) const; const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; + const MachOFormat::SymtabLoadCommand * + getSymtabLoadCommand(LoadCommandInfo LCI) const; std::size_t getSectionIndex(DataRefImpl Sec) const; void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 4d9186490f..e2b0468b9a 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -30,8 +30,7 @@ namespace object { MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) : ObjectFile(Binary::ID_MachO, Object, ec), - MachOObj(MOO), - RegisteredStringTable(std::numeric_limits::max()) { + MachOObj(MOO) { DataRefImpl DRI; moveToNextSection(DRI); uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; @@ -62,13 +61,20 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ +const MachOFormat::SymtabLoadCommand * +MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const { + StringRef Data = MachOObj->getData(LCI.Offset, + sizeof(MachOFormat::SymtabLoadCommand)); + return reinterpret_cast(Data.data()); +} + void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Symtab) { - InMemoryStruct SymtabLoadCmd; - MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = + getSymtabLoadCommand(LCI); if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) return; } @@ -80,15 +86,16 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { const MachOFormat::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - InMemoryStruct SymtabLoadCmd; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = + getSymtabLoadCommand(LCI); - if (RegisteredStringTable != DRI.d.a) { - MachOObj->RegisterStringTable(*SymtabLoadCmd); - RegisteredStringTable = DRI.d.a; - } + return getSymbolTableEntry(DRI, SymtabLoadCmd); +} +const MachOFormat::SymbolTableEntry * +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + @@ -100,15 +107,16 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { const MachOFormat::Symbol64TableEntry* MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - InMemoryStruct SymtabLoadCmd; LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - MachOObj->ReadSymtabLoadCommand(LCI, SymtabLoadCmd); + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = + getSymtabLoadCommand(LCI); - if (RegisteredStringTable != DRI.d.a) { - MachOObj->RegisterStringTable(*SymtabLoadCmd); - RegisteredStringTable = DRI.d.a; - } + return getSymbol64TableEntry(DRI, SymtabLoadCmd); +} +const MachOFormat::Symbol64TableEntry* +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + @@ -128,13 +136,28 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, StringRef &Result) const { + LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = + getSymtabLoadCommand(LCI); + + StringRef StringTable = + MachOObj->getData(SymtabLoadCmd->StringTableOffset, + SymtabLoadCmd->StringTableSize); + + uint32_t StringIndex; if (MachOObj->is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); - Result = MachOObj->getStringAtIndex(Entry->StringIndex); + const MachOFormat::Symbol64TableEntry *Entry = + getSymbol64TableEntry(DRI, SymtabLoadCmd); + StringIndex = Entry->StringIndex; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); - Result = MachOObj->getStringAtIndex(Entry->StringIndex); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI, SymtabLoadCmd); + StringIndex = Entry->StringIndex; } + + const char *Start = &StringTable.data()[StringIndex]; + Result = StringRef(Start); + return object_error::success; } -- cgit v1.2.3-70-g09d2 From 68d287d19e6918f46e58456fdd237c049efe372e Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 6 Apr 2013 03:50:05 +0000 Subject: Remove last use of InMemoryStruct from MachOObjectFile.cpp. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178948 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 32 ++++++++++++++++++++++++++++++++ lib/Object/MachOObjectFile.cpp | 23 +++++++++++++++++++---- 2 files changed, 51 insertions(+), 4 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index d6abaf1be2..8543ecc829 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -85,6 +85,34 @@ namespace MachOFormat { support::ulittle32_t StringTableOffset; support::ulittle32_t StringTableSize; }; + + struct SegmentLoadCommand { + support::ulittle32_t Type; + support::ulittle32_t Size; + char Name[16]; + support::ulittle32_t VMAddress; + support::ulittle32_t VMSize; + support::ulittle32_t FileOffset; + support::ulittle32_t FileSize; + support::ulittle32_t MaxVMProtection; + support::ulittle32_t InitialVMProtection; + support::ulittle32_t NumSections; + support::ulittle32_t Flags; + }; + + struct Segment64LoadCommand { + support::ulittle32_t Type; + support::ulittle32_t Size; + char Name[16]; + support::ulittle64_t VMAddress; + support::ulittle64_t VMSize; + support::ulittle64_t FileOffset; + support::ulittle64_t FileSize; + support::ulittle32_t MaxVMProtection; + support::ulittle32_t InitialVMProtection; + support::ulittle32_t NumSections; + support::ulittle32_t Flags; + }; } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -204,6 +232,10 @@ private: const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; const MachOFormat::SymtabLoadCommand * getSymtabLoadCommand(LoadCommandInfo LCI) const; + const MachOFormat::SegmentLoadCommand * + getSegmentLoadCommand(LoadCommandInfo LCI) const; + const MachOFormat::Segment64LoadCommand * + getSegment64LoadCommand(LoadCommandInfo LCI) const; std::size_t getSectionIndex(DataRefImpl Sec) const; void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e2b0468b9a..1eb14f31ff 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -68,6 +68,21 @@ MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const { return reinterpret_cast(Data.data()); } +const MachOFormat::SegmentLoadCommand * +MachOObjectFile::getSegmentLoadCommand(LoadCommandInfo LCI) const { + StringRef Data = MachOObj->getData(LCI.Offset, + sizeof(MachOFormat::SegmentLoadCommand)); + return reinterpret_cast(Data.data()); +} + +const MachOFormat::Segment64LoadCommand * +MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const { + StringRef Data = MachOObj->getData(LCI.Offset, + sizeof(MachOFormat::Segment64LoadCommand)); + return + reinterpret_cast(Data.data()); +} + void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { @@ -436,13 +451,13 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { while (DRI.d.a < LoadCommandCount) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Segment) { - InMemoryStruct SegmentLoadCmd; - MachOObj->ReadSegmentLoadCommand(LCI, SegmentLoadCmd); + const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = + getSegmentLoadCommand(LCI); if (DRI.d.b < SegmentLoadCmd->NumSections) return; } else if (LCI.Command.Type == macho::LCT_Segment64) { - InMemoryStruct Segment64LoadCmd; - MachOObj->ReadSegment64LoadCommand(LCI, Segment64LoadCmd); + const MachOFormat::Segment64LoadCommand *Segment64LoadCmd = + getSegment64LoadCommand(LCI); if (DRI.d.b < Segment64LoadCmd->NumSections) return; } -- cgit v1.2.3-70-g09d2 From 196abbffe9b7a760593d68b99cbb5f961efc8e2a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 14:40:18 +0000 Subject: Remove last use of InMemoryStruct in llvm-objdump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178979 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 10 ++++++++++ lib/Object/MachOObjectFile.cpp | 8 ++++++++ tools/llvm-objdump/MachODump.cpp | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8543ecc829..f026e6c69d 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -113,6 +113,13 @@ namespace MachOFormat { support::ulittle32_t NumSections; support::ulittle32_t Flags; }; + + struct LinkeditDataLoadCommand { + support::ulittle32_t Type; + support::ulittle32_t Size; + support::ulittle32_t DataOffset; + support::ulittle32_t DataSize; + }; } typedef MachOObject::LoadCommandInfo LoadCommandInfo; @@ -145,6 +152,9 @@ public: ArrayRef getSectionRawName(DataRefImpl Sec) const; ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; + const MachOFormat::LinkeditDataLoadCommand * + getLinkeditDataLoadCommand(LoadCommandInfo LCI) const; + MachOObject *getObject() { return MachOObj.get(); } static inline bool classof(const Binary *v) { diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 1eb14f31ff..94827693e9 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -75,6 +75,14 @@ MachOObjectFile::getSegmentLoadCommand(LoadCommandInfo LCI) const { return reinterpret_cast(Data.data()); } +const MachOFormat::LinkeditDataLoadCommand * +MachOObjectFile::getLinkeditDataLoadCommand(LoadCommandInfo LCI) const { + StringRef Data = MachOObj->getData(LCI.Offset, + sizeof(MachOFormat::LinkeditDataLoadCommand)); + return + reinterpret_cast(Data.data()); +} + const MachOFormat::Segment64LoadCommand * MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const { StringRef Data = MachOObj->getData(LCI.Offset, diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index b122cd3b7a..894e769115 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -223,8 +223,8 @@ static void getSectionsAndSymbols(const macho::Header &Header, if (LCI.Command.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - InMemoryStruct LLC; - MachOObj->getObject()->ReadLinkeditDataLoadCommand(LCI, LLC); + const MachOFormat::LinkeditDataLoadCommand *LLC = + MachOObj->getLinkeditDataLoadCommand(LCI); MachOObj->getObject()->ReadULEB128s(LLC->DataOffset, FoundFns); } -- cgit v1.2.3-70-g09d2 From 0be4eafd9c90d5e584b951fe2970f024341486c3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 15:46:05 +0000 Subject: Remove two uses of getObject. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178985 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 1 + lib/Object/MachOObjectFile.cpp | 3 +++ tools/llvm-readobj/MachODumper.cpp | 15 ++------------- 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index aeb6bd3dc8..2e504155ac 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -160,6 +160,7 @@ public: getSymbol64TableEntry(DataRefImpl DRI) const; const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; + bool is64Bit() const; const MachOObject *getObject() const { return MachOObj.get(); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 94827693e9..86677231c4 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -41,6 +41,9 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, } } +bool MachOObjectFile::is64Bit() const { + return MachOObj->is64Bit(); +} ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 8f37b9a183..190baa229b 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -157,20 +157,10 @@ namespace { }; } -static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Segment64) - return true; - assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); - return false; -} - static void getSection(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSection &Section) { - const MachOObject *MachOObj = Obj->getObject(); - - if (is64BitLoadCommand(MachOObj, DRI)) { + if (Obj->is64Bit()) { const MachOFormat::Section64 *Sect = Obj->getSection64(DRI); Section.Address = Sect->Address; @@ -200,8 +190,7 @@ static void getSection(const MachOObjectFile *Obj, static void getSymbol(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - const MachOObject *MachOObj = Obj->getObject(); - if (MachOObj->is64Bit()) { + if (Obj->is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = Obj->getSymbol64TableEntry( DRI); Symbol.StringIndex = Entry->StringIndex; -- cgit v1.2.3-70-g09d2 From 3eff318cbac281d46e8c8dfef16ffccbceebc855 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 16:07:35 +0000 Subject: Remove MachOObjectFile::getObject. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178986 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 5 +++-- lib/Object/MachOObjectFile.cpp | 14 ++++++++++++++ tools/llvm-objdump/MachODump.cpp | 18 ++++++++---------- 3 files changed, 25 insertions(+), 12 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 2e504155ac..f3b47a0f33 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -161,8 +161,9 @@ public: const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; - - const MachOObject *getObject() const { return MachOObj.get(); } + const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; + const macho::Header &getHeader() const; static inline bool classof(const Binary *v) { return v->isMachO(); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 86677231c4..fdce21bfd7 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -45,6 +45,20 @@ bool MachOObjectFile::is64Bit() const { return MachOObj->is64Bit(); } +const LoadCommandInfo & +MachOObjectFile::getLoadCommandInfo(unsigned Index) const { + return MachOObj->getLoadCommandInfo(Index); +} + +void MachOObjectFile::ReadULEB128s(uint64_t Index, + SmallVectorImpl &Out) const { + return MachOObj->ReadULEB128s(Index, Out); +} + +const macho::Header &MachOObjectFile::getHeader() const { + return MachOObj->getHeader(); +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; std::string Err; diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 282f04db2e..d3f29d2d50 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -52,7 +52,7 @@ static cl::opt static cl::opt DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObject *MachOObj) { +static const Target *GetTarget(const MachOObjectFile *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); @@ -108,7 +108,7 @@ struct SymbolSorter { // Print additional information about an address, if available. static void DumpAddress(uint64_t Address, ArrayRef Sections, - const MachOObject *MachOObj, raw_ostream &OS) { + const MachOObjectFile *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { uint64_t SectAddr = 0, SectSize = 0; Sections[i].getAddress(SectAddr); @@ -218,15 +218,14 @@ static void getSectionsAndSymbols(const macho::Header &Header, } for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = - MachOObj->getObject()->getLoadCommandInfo(i); + const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); if (LCI.Command.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. const MachOFormat::LinkeditDataLoadCommand *LLC = MachOObj->getLinkeditDataLoadCommand(LCI); - MachOObj->getObject()->ReadULEB128s(LLC->DataOffset, FoundFns); + MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); } } } @@ -241,9 +240,8 @@ void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr MachOOF(static_cast( ObjectFile::createMachOObjectFile(Buff.take()))); - const MachOObject *MachOObj = MachOOF->getObject(); - const Target *TheTarget = GetTarget(MachOObj); + const Target *TheTarget = GetTarget(MachOOF.get()); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -271,7 +269,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const macho::Header &Header = MachOObj->getHeader(); + const macho::Header &Header = MachOOF->getHeader(); std::vector Sections; std::vector Symbols; @@ -580,7 +578,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Relocs[j].second.getName(SymName); outs() << "\t# " << SymName << ' '; - DumpAddress(Addr, Sections, MachOObj, outs()); + DumpAddress(Addr, Sections, MachOOF.get(), outs()); } // If this instructions contains an address, see if we can evaluate @@ -589,7 +587,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Inst.Address, Inst.Size); if (targ != -1ULL) - DumpAddress(targ, Sections, MachOObj, outs()); + DumpAddress(targ, Sections, MachOOF.get(), outs()); // Print debug info. if (diContext) { -- cgit v1.2.3-70-g09d2 From 2c6f997290f589b80da903e33718175666557dd7 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 16:40:00 +0000 Subject: Remove unused argument. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178987 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 3 +-- include/llvm/Object/ObjectFile.h | 2 +- lib/Object/COFFObjectFile.cpp | 2 +- lib/Object/MachOObjectFile.cpp | 2 +- lib/Object/ObjectFile.cpp | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 8ea5e46e09..dbae933445 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -2189,8 +2189,7 @@ ELFObjectFile::ELFObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(getELFType( static_cast(ELFT::TargetEndianness) == support::little, ELFT::Is64Bits), - Object, - ec) + Object) , isDyldELFObject(false) , SectionHeaderTable(0) , dot_shstrtab_sec(0) diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index 6a66653fe2..074a752365 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -276,7 +276,7 @@ class ObjectFile : public Binary { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec); + ObjectFile(unsigned int Type, MemoryBuffer *source); const uint8_t *base() const { return reinterpret_cast(Data->getBufferStart()); diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index ca90e0e3c3..46acd4d537 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -429,7 +429,7 @@ relocation_iterator COFFObjectFile::getSectionRelEnd(DataRefImpl Sec) const { } COFFObjectFile::COFFObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(Binary::ID_COFF, Object, ec) + : ObjectFile(Binary::ID_COFF, Object) , Header(0) , SectionTable(0) , SymbolTable(0) diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index fdce21bfd7..6f888faf9c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -29,7 +29,7 @@ namespace object { MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec) - : ObjectFile(Binary::ID_MachO, Object, ec), + : ObjectFile(Binary::ID_MachO, Object), MachOObj(MOO) { DataRefImpl DRI; moveToNextSection(DRI); diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 860c87be98..518959aa05 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -23,7 +23,7 @@ using namespace object; void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source, error_code &ec) +ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) : Binary(Type, source) { } -- cgit v1.2.3-70-g09d2 From 6f1f33915a09a862fd83e7c9f1dc465c2b9e427c Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 16:58:48 +0000 Subject: Construct MachOObject in MachOObjectFile's constructor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178988 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 2 +- lib/Object/MachOObjectFile.cpp | 36 ++++++++++++++++++++---------------- 2 files changed, 21 insertions(+), 17 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index f3b47a0f33..9bd591a540 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -126,7 +126,7 @@ typedef MachOObject::LoadCommandInfo LoadCommandInfo; class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, error_code &ec); + MachOObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 6f888faf9c..c817942ca1 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -27,10 +27,23 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, MachOObject *MOO, - error_code &ec) - : ObjectFile(Binary::ID_MachO, Object), - MachOObj(MOO) { +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) + : ObjectFile(Binary::ID_MachO, Object) { + // 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(Object->getBuffer(), + Object->getBufferIdentifier(), false); + std::string ErrorStr; + MachOObj.reset(MachOObject::LoadFromBuffer(NewBuffer, &ErrorStr)); + if (!MachOObj) { + ec = object_error::parse_failed; + return; + } + DataRefImpl DRI; moveToNextSection(DRI); uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; @@ -61,19 +74,10 @@ const macho::Header &MachOObjectFile::getHeader() const { ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; - std::string Err; - MachOObject *MachOObj = MachOObject::LoadFromBuffer(Buffer, &Err); - if (!MachOObj) + ObjectFile *Ret = new MachOObjectFile(Buffer, ec); + if (ec) return NULL; - // 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); + return Ret; } /*===-- Symbols -----------------------------------------------------------===*/ -- cgit v1.2.3-70-g09d2 From f305127f0b46d0782f53c8aeab448f9dfeb769ec Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 17:41:59 +0000 Subject: Use getLoadCommandInfo instead of MachOObj->getLoadCommandInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178989 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c817942ca1..e20ca2b353 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -115,7 +115,7 @@ MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const { void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Symtab) { const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = getSymtabLoadCommand(LCI); @@ -130,7 +130,7 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { const MachOFormat::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = getSymtabLoadCommand(LCI); @@ -151,7 +151,7 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, const MachOFormat::Symbol64TableEntry* MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = getSymtabLoadCommand(LCI); @@ -180,7 +180,7 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, StringRef &Result) const { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = getSymtabLoadCommand(LCI); @@ -478,7 +478,7 @@ StringRef MachOObjectFile::getLoadName() const { void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Segment) { const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = getSegmentLoadCommand(LCI); @@ -504,7 +504,8 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, return object_error::success; } -static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { +static bool is64BitLoadCommand(const MachOObjectFile *MachOObj, + DataRefImpl DRI) { LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); if (LCI.Command.Type == macho::LCT_Segment64) return true; @@ -513,8 +514,8 @@ static bool is64BitLoadCommand(const MachOObject *MachOObj, DataRefImpl DRI) { } const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { - assert(!is64BitLoadCommand(MachOObj.get(), DRI)); - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + assert(!is64BitLoadCommand(this, DRI)); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + DRI.d.b * sizeof(MachOFormat::Section); StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section)); @@ -530,8 +531,8 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { const MachOFormat::Section64 * MachOObjectFile::getSection64(DataRefImpl DRI) const { - assert(is64BitLoadCommand(MachOObj.get(), DRI)); - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); + assert(is64BitLoadCommand(this, DRI)); + LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + DRI.d.b * sizeof(MachOFormat::Section64); StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64)); @@ -547,7 +548,7 @@ static StringRef parseSegmentOrSectionName(const char *P) { } ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *sec = getSection64(DRI); return ArrayRef(sec->Name); } else { @@ -565,7 +566,7 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - if (is64BitLoadCommand(MachOObj.get(), Sec)) { + if (is64BitLoadCommand(this, Sec)) { const MachOFormat::Section64 *sec = getSection64(Sec); return ArrayRef(sec->SegmentName, 16); } else { @@ -581,7 +582,7 @@ StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Address; } else { @@ -593,7 +594,7 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Size; } else { @@ -605,7 +606,7 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = MachOObj->getData(Sect->Offset, Sect->Size); } else { @@ -617,7 +618,7 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = uint64_t(1) << Sect->Align; } else { @@ -629,7 +630,7 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { - if (is64BitLoadCommand(MachOObj.get(), DRI)) { + if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } else { @@ -730,7 +731,7 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; - if (is64BitLoadCommand(MachOObj.get(), Sec)) { + if (is64BitLoadCommand(this, Sec)) { const MachOFormat::Section64 *Sect = getSection64(Sec); last_reloc = Sect->NumRelocationTableEntries; } else { -- cgit v1.2.3-70-g09d2 From 77638d9110d67333e4ea8e6bd3206606a89bc24f Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 18:08:12 +0000 Subject: Add MachOObjectFile::LoadCommandInfo. This avoids using MachOObject::getLoadCommandInfo. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178990 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 17 ++++++++++++++--- lib/Object/MachOObjectFile.cpp | 31 +++++++++++++++++++++++-------- tools/llvm-objdump/MachODump.cpp | 4 ++-- 3 files changed, 39 insertions(+), 13 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 9bd591a540..8b3539a3e1 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -77,6 +77,11 @@ namespace MachOFormat { support::ulittle64_t Value; }; + struct LoadCommand { + support::ulittle32_t Type; + support::ulittle32_t Size; + }; + struct SymtabLoadCommand { support::ulittle32_t Type; support::ulittle32_t Size; @@ -122,10 +127,16 @@ namespace MachOFormat { }; } -typedef MachOObject::LoadCommandInfo LoadCommandInfo; - class MachOObjectFile : public ObjectFile { public: + struct LoadCommandInfo { + /// The load command information. + const MachOFormat::LoadCommand *Command; + + /// The offset to the start of the load command in memory. + uint64_t Offset; + }; + MachOObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; @@ -161,7 +172,7 @@ public: const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; - const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; + LoadCommandInfo getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; const macho::Header &getHeader() const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e20ca2b353..dbbc812d14 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -58,9 +58,23 @@ bool MachOObjectFile::is64Bit() const { return MachOObj->is64Bit(); } -const LoadCommandInfo & +MachOObjectFile::LoadCommandInfo MachOObjectFile::getLoadCommandInfo(unsigned Index) const { - return MachOObj->getLoadCommandInfo(Index); + uint64_t Offset; + uint64_t NewOffset = MachOObj->getHeaderSize(); + const MachOFormat::LoadCommand *Load; + unsigned I = 0; + do { + Offset = NewOffset; + StringRef Data = MachOObj->getData(Offset, + sizeof(MachOFormat::LoadCommand)); + Load = reinterpret_cast(Data.data()); + NewOffset = Offset + Load->Size; + ++I; + } while (I != Index + 1); + + LoadCommandInfo Ret = {Load, Offset}; + return Ret; } void MachOObjectFile::ReadULEB128s(uint64_t Index, @@ -116,7 +130,7 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Symtab) { + if (LCI.Command->Type == macho::LCT_Symtab) { const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = getSymtabLoadCommand(LCI); if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) @@ -479,12 +493,12 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Segment) { + if (LCI.Command->Type == macho::LCT_Segment) { const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = getSegmentLoadCommand(LCI); if (DRI.d.b < SegmentLoadCmd->NumSections) return; - } else if (LCI.Command.Type == macho::LCT_Segment64) { + } else if (LCI.Command->Type == macho::LCT_Segment64) { const MachOFormat::Segment64LoadCommand *Segment64LoadCmd = getSegment64LoadCommand(LCI); if (DRI.d.b < Segment64LoadCmd->NumSections) @@ -506,10 +520,11 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, static bool is64BitLoadCommand(const MachOObjectFile *MachOObj, DataRefImpl DRI) { - LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(DRI.d.a); - if (LCI.Command.Type == macho::LCT_Segment64) + MachOObjectFile::LoadCommandInfo LCI = + MachOObj->getLoadCommandInfo(DRI.d.a); + if (LCI.Command->Type == macho::LCT_Segment64) return true; - assert(LCI.Command.Type == macho::LCT_Segment && "Unexpected Type."); + assert(LCI.Command->Type == macho::LCT_Segment && "Unexpected Type."); return false; } diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index d3f29d2d50..44a6221c15 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -218,8 +218,8 @@ static void getSectionsAndSymbols(const macho::Header &Header, } for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - const MachOObject::LoadCommandInfo &LCI = MachOObj->getLoadCommandInfo(i); - if (LCI.Command.Type == macho::LCT_FunctionStarts) { + MachOObjectFile::LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(i); + if (LCI.Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. const MachOFormat::LinkeditDataLoadCommand *LLC = -- cgit v1.2.3-70-g09d2 From 6ab85a81d711b1e9d3bbc02e05812e7f867a7c40 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 18:42:06 +0000 Subject: Remove LoadCommandInfo now that we always have a pointer to the command. LoadCommandInfo was needed to keep a command and its offset in the file. Now that we always have a pointer to the command, we don't need the offset. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178991 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 18 +-------- lib/Object/MachOObjectFile.cpp | 85 +++++++++++++--------------------------- tools/llvm-objdump/MachODump.cpp | 6 +-- 3 files changed, 31 insertions(+), 78 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8b3539a3e1..37ecad0eed 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -129,14 +129,6 @@ namespace MachOFormat { class MachOObjectFile : public ObjectFile { public: - struct LoadCommandInfo { - /// The load command information. - const MachOFormat::LoadCommand *Command; - - /// The offset to the start of the load command in memory. - uint64_t Offset; - }; - MachOObjectFile(MemoryBuffer *Object, error_code &ec); virtual symbol_iterator begin_symbols() const; @@ -163,8 +155,6 @@ public: ArrayRef getSectionRawName(DataRefImpl Sec) const; ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; - const MachOFormat::LinkeditDataLoadCommand * - getLinkeditDataLoadCommand(LoadCommandInfo LCI) const; const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; const MachOFormat::Section *getSection(DataRefImpl DRI) const; const MachOFormat::Symbol64TableEntry * @@ -172,7 +162,7 @@ public: const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; - LoadCommandInfo getLoadCommandInfo(unsigned Index) const; + const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; const macho::Header &getHeader() const; @@ -251,12 +241,6 @@ private: void moveToNextSymbol(DataRefImpl &DRI) const; const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; - const MachOFormat::SymtabLoadCommand * - getSymtabLoadCommand(LoadCommandInfo LCI) const; - const MachOFormat::SegmentLoadCommand * - getSegmentLoadCommand(LoadCommandInfo LCI) const; - const MachOFormat::Segment64LoadCommand * - getSegment64LoadCommand(LoadCommandInfo LCI) const; std::size_t getSectionIndex(DataRefImpl Sec) const; void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index dbbc812d14..002a98cbe6 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -58,7 +58,7 @@ bool MachOObjectFile::is64Bit() const { return MachOObj->is64Bit(); } -MachOObjectFile::LoadCommandInfo +const MachOFormat::LoadCommand * MachOObjectFile::getLoadCommandInfo(unsigned Index) const { uint64_t Offset; uint64_t NewOffset = MachOObj->getHeaderSize(); @@ -73,8 +73,7 @@ MachOObjectFile::getLoadCommandInfo(unsigned Index) const { ++I; } while (I != Index + 1); - LoadCommandInfo Ret = {Load, Offset}; - return Ret; + return Load; } void MachOObjectFile::ReadULEB128s(uint64_t Index, @@ -96,43 +95,13 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -const MachOFormat::SymtabLoadCommand * -MachOObjectFile::getSymtabLoadCommand(LoadCommandInfo LCI) const { - StringRef Data = MachOObj->getData(LCI.Offset, - sizeof(MachOFormat::SymtabLoadCommand)); - return reinterpret_cast(Data.data()); -} - -const MachOFormat::SegmentLoadCommand * -MachOObjectFile::getSegmentLoadCommand(LoadCommandInfo LCI) const { - StringRef Data = MachOObj->getData(LCI.Offset, - sizeof(MachOFormat::SegmentLoadCommand)); - return reinterpret_cast(Data.data()); -} - -const MachOFormat::LinkeditDataLoadCommand * -MachOObjectFile::getLinkeditDataLoadCommand(LoadCommandInfo LCI) const { - StringRef Data = MachOObj->getData(LCI.Offset, - sizeof(MachOFormat::LinkeditDataLoadCommand)); - return - reinterpret_cast(Data.data()); -} - -const MachOFormat::Segment64LoadCommand * -MachOObjectFile::getSegment64LoadCommand(LoadCommandInfo LCI) const { - StringRef Data = MachOObj->getData(LCI.Offset, - sizeof(MachOFormat::Segment64LoadCommand)); - return - reinterpret_cast(Data.data()); -} - void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - if (LCI.Command->Type == macho::LCT_Symtab) { + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + if (Command->Type == macho::LCT_Symtab) { const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - getSymtabLoadCommand(LCI); + reinterpret_cast(Command); if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) return; } @@ -144,9 +113,9 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { const MachOFormat::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - getSymtabLoadCommand(LCI); + reinterpret_cast(Command); return getSymbolTableEntry(DRI, SymtabLoadCmd); } @@ -165,9 +134,9 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, const MachOFormat::Symbol64TableEntry* MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - getSymtabLoadCommand(LCI); + reinterpret_cast(Command); return getSymbol64TableEntry(DRI, SymtabLoadCmd); } @@ -194,9 +163,9 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, StringRef &Result) const { - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - getSymtabLoadCommand(LCI); + reinterpret_cast(Command); StringRef StringTable = MachOObj->getData(SymtabLoadCmd->StringTableOffset, @@ -492,15 +461,15 @@ StringRef MachOObjectFile::getLoadName() const { void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - if (LCI.Command->Type == macho::LCT_Segment) { + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + if (Command->Type == macho::LCT_Segment) { const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = - getSegmentLoadCommand(LCI); + reinterpret_cast(Command); if (DRI.d.b < SegmentLoadCmd->NumSections) return; - } else if (LCI.Command->Type == macho::LCT_Segment64) { + } else if (Command->Type == macho::LCT_Segment64) { const MachOFormat::Segment64LoadCommand *Segment64LoadCmd = - getSegment64LoadCommand(LCI); + reinterpret_cast(Command); if (DRI.d.b < Segment64LoadCmd->NumSections) return; } @@ -520,21 +489,21 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, static bool is64BitLoadCommand(const MachOObjectFile *MachOObj, DataRefImpl DRI) { - MachOObjectFile::LoadCommandInfo LCI = + const MachOFormat::LoadCommand *Command = MachOObj->getLoadCommandInfo(DRI.d.a); - if (LCI.Command->Type == macho::LCT_Segment64) + if (Command->Type == macho::LCT_Segment64) return true; - assert(LCI.Command->Type == macho::LCT_Segment && "Unexpected Type."); + assert(Command->Type == macho::LCT_Segment && "Unexpected Type."); return false; } const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { assert(!is64BitLoadCommand(this, DRI)); - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - unsigned SectionOffset = LCI.Offset + sizeof(macho::SegmentLoadCommand) + + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + uintptr_t CommandAddr = reinterpret_cast(Command); + uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) + DRI.d.b * sizeof(MachOFormat::Section); - StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section)); - return reinterpret_cast(Data.data()); + return reinterpret_cast(SectionAddr); } std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { @@ -547,11 +516,11 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { const MachOFormat::Section64 * MachOObjectFile::getSection64(DataRefImpl DRI) const { assert(is64BitLoadCommand(this, DRI)); - LoadCommandInfo LCI = getLoadCommandInfo(DRI.d.a); - unsigned SectionOffset = LCI.Offset + sizeof(macho::Segment64LoadCommand) + + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + uintptr_t CommandAddr = reinterpret_cast(Command); + uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) + DRI.d.b * sizeof(MachOFormat::Section64); - StringRef Data = MachOObj->getData(SectionOffset, sizeof(MachOFormat::Section64)); - return reinterpret_cast(Data.data()); + return reinterpret_cast(SectionAddr); } static StringRef parseSegmentOrSectionName(const char *P) { diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 44a6221c15..9275fe147a 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -218,12 +218,12 @@ static void getSectionsAndSymbols(const macho::Header &Header, } for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { - MachOObjectFile::LoadCommandInfo LCI = MachOObj->getLoadCommandInfo(i); - if (LCI.Command->Type == macho::LCT_FunctionStarts) { + const MachOFormat::LoadCommand *Command = MachOObj->getLoadCommandInfo(i); + if (Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. const MachOFormat::LinkeditDataLoadCommand *LLC = - MachOObj->getLinkeditDataLoadCommand(LCI); + reinterpret_cast(Command); MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); } -- cgit v1.2.3-70-g09d2 From 0f08eb135997a94ba37f79aaeb306993c21bbae2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 19:05:30 +0000 Subject: Implement MachOObjectFile::getHeaderSize and MachOObjectFile::getData. These were the last missing forwarding functions. Also consistently use the forwarding functions instead of using MachOObj directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178992 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 2 + lib/Object/MachOObjectFile.cpp | 85 ++++++++++++++++++++++-------------------- 2 files changed, 46 insertions(+), 41 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 37ecad0eed..4cdf091fc1 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -165,6 +165,8 @@ public: const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; const macho::Header &getHeader() const; + unsigned getHeaderSize() const; + StringRef getData(size_t Offset, size_t Size) const; static inline bool classof(const Binary *v) { return v->isMachO(); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 002a98cbe6..f011da1e3a 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -46,7 +46,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) DataRefImpl DRI; moveToNextSection(DRI); - uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { Sections.push_back(DRI); DRI.d.b++; @@ -61,13 +61,12 @@ bool MachOObjectFile::is64Bit() const { const MachOFormat::LoadCommand * MachOObjectFile::getLoadCommandInfo(unsigned Index) const { uint64_t Offset; - uint64_t NewOffset = MachOObj->getHeaderSize(); + uint64_t NewOffset = getHeaderSize(); const MachOFormat::LoadCommand *Load; unsigned I = 0; do { Offset = NewOffset; - StringRef Data = MachOObj->getData(Offset, - sizeof(MachOFormat::LoadCommand)); + StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand)); Load = reinterpret_cast(Data.data()); NewOffset = Offset + Load->Size; ++I; @@ -85,6 +84,14 @@ const macho::Header &MachOObjectFile::getHeader() const { return MachOObj->getHeader(); } +unsigned MachOObjectFile::getHeaderSize() const { + return MachOObj->getHeaderSize(); +} + +StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { + return MachOObj->getData(Offset, Size); +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { error_code ec; ObjectFile *Ret = new MachOObjectFile(Buffer, ec); @@ -96,7 +103,7 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Symtab) { @@ -127,8 +134,7 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + Index * sizeof(macho::SymbolTableEntry)); - StringRef Data = MachOObj->getData(Offset, - sizeof(MachOFormat::SymbolTableEntry)); + StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); return reinterpret_cast(Data.data()); } @@ -148,8 +154,7 @@ MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + Index * sizeof(macho::Symbol64TableEntry)); - StringRef Data = MachOObj->getData(Offset, - sizeof(MachOFormat::Symbol64TableEntry)); + StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry)); return reinterpret_cast(Data.data()); } @@ -167,12 +172,11 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = reinterpret_cast(Command); - StringRef StringTable = - MachOObj->getData(SymtabLoadCmd->StringTableOffset, - SymtabLoadCmd->StringTableSize); + StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, + SymtabLoadCmd->StringTableSize); uint32_t StringIndex; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI, SymtabLoadCmd); StringIndex = Entry->StringIndex; @@ -190,7 +194,7 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, uint64_t &Result) const { - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Result = Entry->Value; if (Entry->SectionIndex) { @@ -213,7 +217,7 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, uint64_t &Result) const { - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Result = Entry->Value; } else { @@ -225,11 +229,11 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { - uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader().NumLoadCommands; uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; @@ -297,7 +301,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, char &Result) const { uint8_t Type, Flags; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); Type = Entry->Type; Flags = Entry->Flags; @@ -331,7 +335,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, uint32_t &Result) const { uint16_t MachOFlags; uint8_t MachOType; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); MachOFlags = Entry->Flags; MachOType = Entry->Type; @@ -368,7 +372,7 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { uint8_t index; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); index = Entry->SectionIndex; } else { @@ -387,7 +391,7 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const { uint8_t n_type; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); n_type = Entry->Type; } else { @@ -427,7 +431,7 @@ symbol_iterator MachOObjectFile::begin_symbols() const { symbol_iterator MachOObjectFile::end_symbols() const { DataRefImpl DRI; - DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.a = getHeader().NumLoadCommands; return symbol_iterator(SymbolRef(DRI, this)); } @@ -459,7 +463,7 @@ StringRef MachOObjectFile::getLoadName() const { /*===-- Sections ----------------------------------------------------------===*/ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = MachOObj->getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader().NumLoadCommands; while (DRI.d.a < LoadCommandCount) { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Segment) { @@ -592,10 +596,10 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { if (is64BitLoadCommand(this, DRI)) { const MachOFormat::Section64 *Sect = getSection64(DRI); - Result = MachOObj->getData(Sect->Offset, Sect->Size); + Result = getData(Sect->Offset, Sect->Size); } else { const MachOFormat::Section *Sect = getSection(DRI); - Result = MachOObj->getData(Sect->Offset, Sect->Size); + Result = getData(Sect->Offset, Sect->Size); } return object_error::success; } @@ -654,7 +658,7 @@ error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, bool &Result) const { - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || @@ -695,7 +699,7 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, getSectionSize(Sec, SectEnd); SectEnd += SectBegin; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); @@ -736,7 +740,7 @@ section_iterator MachOObjectFile::begin_sections() const { section_iterator MachOObjectFile::end_sections() const { DataRefImpl DRI; - DRI.d.a = MachOObj->getHeader().NumLoadCommands; + DRI.d.a = getHeader().NumLoadCommands; return section_iterator(SectionRef(DRI, this)); } @@ -745,7 +749,7 @@ section_iterator MachOObjectFile::end_sections() const { const MachOFormat::RelocationEntry * MachOObjectFile::getRelocation(DataRefImpl Rel) const { uint32_t relOffset; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } else { @@ -753,8 +757,7 @@ MachOObjectFile::getRelocation(DataRefImpl Rel) const { relOffset = Sect->RelocationTableOffset; } uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); - StringRef Data = - MachOObj->getData(Offset, sizeof(MachOFormat::RelocationEntry)); + StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry)); return reinterpret_cast(Data.data()); } @@ -767,7 +770,7 @@ error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { const uint8_t* sectAddress = 0; - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Address; } else { @@ -813,7 +816,7 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, for (unsigned i = 0; i < SymbolIdx; i++) { Sym.d.b++; moveToNextSymbol(Sym); - assert(Sym.d.a < MachOObj->getHeader().NumLoadCommands && + assert(Sym.d.a < getHeader().NumLoadCommands && "Relocation symbol index out of range!"); } } @@ -934,7 +937,7 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, Res = 0; if (!isExtern) { const uint8_t* sectAddress = base(); - if (MachOObj->is64Bit()) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Offset; } else { @@ -1292,12 +1295,12 @@ error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, /*===-- Miscellaneous -----------------------------------------------------===*/ uint8_t MachOObjectFile::getBytesInAddress() const { - return MachOObj->is64Bit() ? 8 : 4; + return is64Bit() ? 8 : 4; } StringRef MachOObjectFile::getFileFormatName() const { - if (!MachOObj->is64Bit()) { - switch (MachOObj->getHeader().CPUType) { + if (!is64Bit()) { + switch (getHeader().CPUType) { case llvm::MachO::CPUTypeI386: return "Mach-O 32-bit i386"; case llvm::MachO::CPUTypeARM: @@ -1305,18 +1308,18 @@ StringRef MachOObjectFile::getFileFormatName() const { case llvm::MachO::CPUTypePowerPC: return "Mach-O 32-bit ppc"; default: - assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && + assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && "64-bit object file when we're not 64-bit?"); return "Mach-O 32-bit unknown"; } } // Make sure the cpu type has the correct mask. - assert((MachOObj->getHeader().CPUType & llvm::MachO::CPUArchABI64) + assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) == llvm::MachO::CPUArchABI64 && "32-bit object file when we're 64-bit?"); - switch (MachOObj->getHeader().CPUType) { + switch (getHeader().CPUType) { case llvm::MachO::CPUTypeX86_64: return "Mach-O 64-bit x86-64"; case llvm::MachO::CPUTypePowerPC64: @@ -1327,7 +1330,7 @@ StringRef MachOObjectFile::getFileFormatName() const { } unsigned MachOObjectFile::getArch() const { - switch (MachOObj->getHeader().CPUType) { + switch (getHeader().CPUType) { case llvm::MachO::CPUTypeI386: return Triple::x86; case llvm::MachO::CPUTypeX86_64: -- cgit v1.2.3-70-g09d2 From 433611bdf395d08093e3edd52846c1774b46caf2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 19:26:57 +0000 Subject: Implement MachOObjectFile::getHeader directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178994 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 12 +++++++++++- lib/Object/MachOObjectFile.cpp | 29 +++++++++++++++-------------- tools/llvm-objdump/MachODump.cpp | 8 ++++---- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 4cdf091fc1..0d20146aae 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -125,6 +125,16 @@ namespace MachOFormat { support::ulittle32_t DataOffset; support::ulittle32_t DataSize; }; + + struct Header { + support::ulittle32_t Magic; + support::ulittle32_t CPUType; + support::ulittle32_t CPUSubtype; + support::ulittle32_t FileType; + support::ulittle32_t NumLoadCommands; + support::ulittle32_t SizeOfLoadCommands; + support::ulittle32_t Flags; + }; } class MachOObjectFile : public ObjectFile { @@ -164,7 +174,7 @@ public: bool is64Bit() const; const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - const macho::Header &getHeader() const; + const MachOFormat::Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index f011da1e3a..31e8be0f94 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -46,7 +46,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) DataRefImpl DRI; moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { Sections.push_back(DRI); DRI.d.b++; @@ -80,8 +80,9 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, return MachOObj->ReadULEB128s(Index, Out); } -const macho::Header &MachOObjectFile::getHeader() const { - return MachOObj->getHeader(); +const MachOFormat::Header *MachOObjectFile::getHeader() const { + StringRef Data = getData(0, sizeof(MachOFormat::Header)); + return reinterpret_cast(Data.data()); } unsigned MachOObjectFile::getHeaderSize() const { @@ -103,7 +104,7 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Symtab) { @@ -229,7 +230,7 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; @@ -431,7 +432,7 @@ symbol_iterator MachOObjectFile::begin_symbols() const { symbol_iterator MachOObjectFile::end_symbols() const { DataRefImpl DRI; - DRI.d.a = getHeader().NumLoadCommands; + DRI.d.a = getHeader()->NumLoadCommands; return symbol_iterator(SymbolRef(DRI, this)); } @@ -463,7 +464,7 @@ StringRef MachOObjectFile::getLoadName() const { /*===-- Sections ----------------------------------------------------------===*/ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader().NumLoadCommands; + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Segment) { @@ -740,7 +741,7 @@ section_iterator MachOObjectFile::begin_sections() const { section_iterator MachOObjectFile::end_sections() const { DataRefImpl DRI; - DRI.d.a = getHeader().NumLoadCommands; + DRI.d.a = getHeader()->NumLoadCommands; return section_iterator(SectionRef(DRI, this)); } @@ -816,7 +817,7 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, for (unsigned i = 0; i < SymbolIdx; i++) { Sym.d.b++; moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader().NumLoadCommands && + assert(Sym.d.a < getHeader()->NumLoadCommands && "Relocation symbol index out of range!"); } } @@ -1300,7 +1301,7 @@ uint8_t MachOObjectFile::getBytesInAddress() const { StringRef MachOObjectFile::getFileFormatName() const { if (!is64Bit()) { - switch (getHeader().CPUType) { + switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: return "Mach-O 32-bit i386"; case llvm::MachO::CPUTypeARM: @@ -1308,18 +1309,18 @@ StringRef MachOObjectFile::getFileFormatName() const { case llvm::MachO::CPUTypePowerPC: return "Mach-O 32-bit ppc"; default: - assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) == 0 && + assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 && "64-bit object file when we're not 64-bit?"); return "Mach-O 32-bit unknown"; } } // Make sure the cpu type has the correct mask. - assert((getHeader().CPUType & llvm::MachO::CPUArchABI64) + assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == llvm::MachO::CPUArchABI64 && "32-bit object file when we're 64-bit?"); - switch (getHeader().CPUType) { + switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeX86_64: return "Mach-O 64-bit x86-64"; case llvm::MachO::CPUTypePowerPC64: @@ -1330,7 +1331,7 @@ StringRef MachOObjectFile::getFileFormatName() const { } unsigned MachOObjectFile::getArch() const { - switch (getHeader().CPUType) { + switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: return Triple::x86; case llvm::MachO::CPUTypeX86_64: diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 9275fe147a..7c6565832e 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -56,7 +56,7 @@ static const Target *GetTarget(const MachOObjectFile *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); - switch (MachOObj->getHeader().CPUType) { + switch (MachOObj->getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: TT.setArch(Triple::ArchType(Triple::x86)); break; @@ -199,7 +199,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -static void getSectionsAndSymbols(const macho::Header &Header, +static void getSectionsAndSymbols(const MachOFormat::Header *Header, MachOObjectFile *MachOObj, std::vector &Sections, std::vector &Symbols, @@ -217,7 +217,7 @@ static void getSectionsAndSymbols(const macho::Header &Header, Sections.push_back(*SI); } - for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + for (unsigned i = 0; i != Header->NumLoadCommands; ++i) { const MachOFormat::LoadCommand *Command = MachOObj->getLoadCommandInfo(i); if (Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later @@ -269,7 +269,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const macho::Header &Header = MachOOF->getHeader(); + const MachOFormat::Header *Header = MachOOF->getHeader(); std::vector Sections; std::vector Symbols; -- cgit v1.2.3-70-g09d2 From c90cc18b6a28bfd49e74ce609e161ef178f5a2d3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 19:31:49 +0000 Subject: Implement MachOObjectFile::getHeaderSize directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178995 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 31e8be0f94..ee42bc8f0b 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -86,7 +86,7 @@ const MachOFormat::Header *MachOObjectFile::getHeader() const { } unsigned MachOObjectFile::getHeaderSize() const { - return MachOObj->getHeaderSize(); + return is64Bit() ? macho::Header64Size : macho::Header32Size; } StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { -- cgit v1.2.3-70-g09d2 From 49698a1e691185a2a94d13edcce5c4a8d0db4762 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 19:38:15 +0000 Subject: Implement MachOObjectFile::is64Bit directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178996 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index ee42bc8f0b..7bb8c19525 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -55,7 +55,8 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) } bool MachOObjectFile::is64Bit() const { - return MachOObj->is64Bit(); + StringRef Magic = getData(0, 4); + return (Magic == "\xFE\xED\xFA\xCF") || (Magic == "\xCF\xFA\xED\xFE"); } const MachOFormat::LoadCommand * -- cgit v1.2.3-70-g09d2 From f1cc8001fd405c3ec903cb6caf97a943bb3898ae Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 19:42:15 +0000 Subject: Implement MachOObjectFile::getData directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178997 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 7bb8c19525..75735418cb 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -91,7 +91,7 @@ unsigned MachOObjectFile::getHeaderSize() const { } StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { - return MachOObj->getData(Offset, Size); + return ObjectFile::getData().substr(Offset, Size); } ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { -- cgit v1.2.3-70-g09d2 From 8764c8979c66966b5af62a0a316acead47c038cd Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sun, 7 Apr 2013 20:01:29 +0000 Subject: Make MachOObjectFile independent from MachOObject. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@178998 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 1 - lib/Object/MachOObjectFile.cpp | 25 +++++++++---------------- 2 files changed, 9 insertions(+), 17 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 0d20146aae..5024d50720 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -236,7 +236,6 @@ protected: virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; private: - OwningPtr MachOObj; typedef SmallVector SectionList; SectionList Sections; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 75735418cb..4fe791c826 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -15,6 +15,7 @@ #include "llvm/Object/MachO.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -29,21 +30,6 @@ namespace object { MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) : ObjectFile(Binary::ID_MachO, Object) { - // 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(Object->getBuffer(), - Object->getBufferIdentifier(), false); - std::string ErrorStr; - MachOObj.reset(MachOObject::LoadFromBuffer(NewBuffer, &ErrorStr)); - if (!MachOObj) { - ec = object_error::parse_failed; - return; - } - DataRefImpl DRI; moveToNextSection(DRI); uint32_t LoadCommandCount = getHeader()->NumLoadCommands; @@ -78,7 +64,14 @@ MachOObjectFile::getLoadCommandInfo(unsigned Index) const { void MachOObjectFile::ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const { - return MachOObj->ReadULEB128s(Index, Out); + DataExtractor extractor(ObjectFile::getData(), true, 0); + + uint32_t offset = Index; + uint64_t data = 0; + while (uint64_t delta = extractor.getULEB128(&offset)) { + data += delta; + Out.push_back(data); + } } const MachOFormat::Header *MachOObjectFile::getHeader() const { -- cgit v1.2.3-70-g09d2 From 9d55c099d628d7835dd1b502cb29c96cae350099 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 8 Apr 2013 13:25:33 +0000 Subject: Add all 4 MachO object types. Use the stored type to implement is64Bits(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179021 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 17 +++++++++++++++-- include/llvm/Object/MachO.h | 2 +- lib/Object/MachOObjectFile.cpp | 13 ++++++++----- 3 files changed, 24 insertions(+), 8 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 8bbcd8b4d4..ac5bfed4bf 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -41,11 +41,17 @@ protected: // Object and children. ID_StartObjects, ID_COFF, + ID_ELF32L, // ELF 32-bit, little endian ID_ELF32B, // ELF 32-bit, big endian ID_ELF64L, // ELF 64-bit, little endian ID_ELF64B, // ELF 64-bit, big endian - ID_MachO, + + ID_MachO32L, // MachO 32-bit, little endian + ID_MachO32B, // MachO 32-bit, big endian + ID_MachO64L, // MachO 64-bit, little endian + ID_MachO64B, // MachO 64-bit, big endian + ID_EndObjects }; @@ -56,6 +62,13 @@ protected: return is64Bits ? ID_ELF64B : ID_ELF32B; } + static unsigned int getMachOType(bool isLE, bool is64Bits) { + if (isLE) + return is64Bits ? ID_MachO64L : ID_MachO32L; + else + return is64Bits ? ID_MachO64B : ID_MachO32B; + } + public: virtual ~Binary(); @@ -79,7 +92,7 @@ public: } bool isMachO() const { - return TypeID == ID_MachO; + return TypeID >= ID_MachO32L && TypeID <= ID_MachO64B; } bool isCOFF() const { diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 5024d50720..226b24ffc9 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -139,7 +139,7 @@ namespace MachOFormat { class MachOObjectFile : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, error_code &ec); + MachOObjectFile(MemoryBuffer *Object, bool Is64bits, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 4fe791c826..24c916c323 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -28,8 +28,9 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) - : ObjectFile(Binary::ID_MachO, Object) { +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits, + error_code &ec) + : ObjectFile(getMachOType(true, Is64bits), Object) { DataRefImpl DRI; moveToNextSection(DRI); uint32_t LoadCommandCount = getHeader()->NumLoadCommands; @@ -41,8 +42,8 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) } bool MachOObjectFile::is64Bit() const { - StringRef Magic = getData(0, 4); - return (Magic == "\xFE\xED\xFA\xCF") || (Magic == "\xCF\xFA\xED\xFE"); + unsigned int Type = getType(); + return Type == ID_MachO64L || Type == ID_MachO64B; } const MachOFormat::LoadCommand * @@ -88,8 +89,10 @@ StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { } ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; - ObjectFile *Ret = new MachOObjectFile(Buffer, ec); + bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; + ObjectFile *Ret = new MachOObjectFile(Buffer, Is64Bits, ec); if (ec) return NULL; return Ret; -- cgit v1.2.3-70-g09d2 From a9408bafcc4ea0a42f9dd7a251845372d64abb8b Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 8 Apr 2013 20:18:53 +0000 Subject: Remove is64BitLoadCommand. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179048 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 24c916c323..86499cf074 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -489,18 +489,8 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, return object_error::success; } -static bool is64BitLoadCommand(const MachOObjectFile *MachOObj, - DataRefImpl DRI) { - const MachOFormat::LoadCommand *Command = - MachOObj->getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Segment64) - return true; - assert(Command->Type == macho::LCT_Segment && "Unexpected Type."); - return false; -} - const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { - assert(!is64BitLoadCommand(this, DRI)); + assert(!is64Bit()); const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast(Command); uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) + @@ -517,7 +507,7 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { const MachOFormat::Section64 * MachOObjectFile::getSection64(DataRefImpl DRI) const { - assert(is64BitLoadCommand(this, DRI)); + assert(is64Bit()); const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast(Command); uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) + @@ -534,7 +524,7 @@ static StringRef parseSegmentOrSectionName(const char *P) { } ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *sec = getSection64(DRI); return ArrayRef(sec->Name); } else { @@ -552,7 +542,7 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - if (is64BitLoadCommand(this, Sec)) { + if (is64Bit()) { const MachOFormat::Section64 *sec = getSection64(Sec); return ArrayRef(sec->SegmentName, 16); } else { @@ -568,7 +558,7 @@ StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Address; } else { @@ -580,7 +570,7 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Size; } else { @@ -592,7 +582,7 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = getData(Sect->Offset, Sect->Size); } else { @@ -604,7 +594,7 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = uint64_t(1) << Sect->Align; } else { @@ -616,7 +606,7 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { - if (is64BitLoadCommand(this, DRI)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } else { @@ -717,7 +707,7 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; - if (is64BitLoadCommand(this, Sec)) { + if (is64Bit()) { const MachOFormat::Section64 *Sect = getSection64(Sec); last_reloc = Sect->NumRelocationTableEntries; } else { -- cgit v1.2.3-70-g09d2 From 335f1d46d82a4d6b5a7317ccc73178a47b62fc25 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 8 Apr 2013 20:45:01 +0000 Subject: Template the MachO types over the word size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179051 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 39 +++++++--- lib/Object/MachOObjectFile.cpp | 151 +++++++++++++++++++++---------------- tools/llvm-readobj/MachODumper.cpp | 11 +-- 3 files changed, 119 insertions(+), 82 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 226b24ffc9..5c50ceb2b6 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -27,7 +27,11 @@ namespace llvm { namespace object { namespace MachOFormat { - struct Section { + template + struct Section; + + template<> + struct Section { char Name[16]; char SegmentName[16]; support::ulittle32_t Address; @@ -41,7 +45,8 @@ namespace MachOFormat { support::ulittle32_t Reserved2; }; - struct Section64 { + template<> + struct Section { char Name[16]; char SegmentName[16]; support::ulittle64_t Address; @@ -61,7 +66,11 @@ namespace MachOFormat { support::ulittle32_t Word1; }; - struct SymbolTableEntry { + template + struct SymbolTableEntry; + + template<> + struct SymbolTableEntry { support::ulittle32_t StringIndex; uint8_t Type; uint8_t SectionIndex; @@ -69,7 +78,8 @@ namespace MachOFormat { support::ulittle32_t Value; }; - struct Symbol64TableEntry { + template<> + struct SymbolTableEntry { support::ulittle32_t StringIndex; uint8_t Type; uint8_t SectionIndex; @@ -91,7 +101,11 @@ namespace MachOFormat { support::ulittle32_t StringTableSize; }; - struct SegmentLoadCommand { + template + struct SegmentLoadCommand; + + template<> + struct SegmentLoadCommand { support::ulittle32_t Type; support::ulittle32_t Size; char Name[16]; @@ -105,7 +119,8 @@ namespace MachOFormat { support::ulittle32_t Flags; }; - struct Segment64LoadCommand { + template<> + struct SegmentLoadCommand { support::ulittle32_t Type; support::ulittle32_t Size; char Name[16]; @@ -165,11 +180,11 @@ public: ArrayRef getSectionRawName(DataRefImpl Sec) const; ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; - const MachOFormat::Section64 *getSection64(DataRefImpl DRI) const; - const MachOFormat::Section *getSection(DataRefImpl DRI) const; - const MachOFormat::Symbol64TableEntry * + const MachOFormat::Section *getSection64(DataRefImpl DRI) const; + const MachOFormat::Section *getSection(DataRefImpl DRI) const; + const MachOFormat::SymbolTableEntry * getSymbol64TableEntry(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry * + const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; @@ -242,11 +257,11 @@ private: void moveToNextSection(DataRefImpl &DRI) const; - const MachOFormat::SymbolTableEntry * + const MachOFormat::SymbolTableEntry * getSymbolTableEntry(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; - const MachOFormat::Symbol64TableEntry * + const MachOFormat::SymbolTableEntry * getSymbol64TableEntry(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 86499cf074..30ab00f450 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -116,7 +116,7 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { } } -const MachOFormat::SymbolTableEntry * +const MachOFormat::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = @@ -125,18 +125,20 @@ MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { return getSymbolTableEntry(DRI, SymtabLoadCmd); } -const MachOFormat::SymbolTableEntry * +const MachOFormat::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + - Index * sizeof(macho::SymbolTableEntry)); - StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); - return reinterpret_cast(Data.data()); + Index * sizeof(MachOFormat::SymbolTableEntry)); + StringRef Data = + getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); + return + reinterpret_cast*>(Data.data()); } -const MachOFormat::Symbol64TableEntry* +const MachOFormat::SymbolTableEntry* MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = @@ -145,15 +147,16 @@ MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { return getSymbol64TableEntry(DRI, SymtabLoadCmd); } -const MachOFormat::Symbol64TableEntry* +const MachOFormat::SymbolTableEntry* MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; uint64_t Offset = (SymbolTableOffset + - Index * sizeof(macho::Symbol64TableEntry)); - StringRef Data = getData(Offset, sizeof(MachOFormat::Symbol64TableEntry)); - return reinterpret_cast(Data.data()); + Index * sizeof(MachOFormat::SymbolTableEntry)); + StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); + return + reinterpret_cast*>(Data.data()); } error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, @@ -175,11 +178,11 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, uint32_t StringIndex; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = + const MachOFormat::SymbolTableEntry *Entry = getSymbol64TableEntry(DRI, SymtabLoadCmd); StringIndex = Entry->StringIndex; } else { - const MachOFormat::SymbolTableEntry *Entry = + const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI, SymtabLoadCmd); StringIndex = Entry->StringIndex; } @@ -193,18 +196,20 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, uint64_t &Result) const { if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(DRI); Result = Entry->Value; if (Entry->SectionIndex) { - const MachOFormat::Section64 *Section = + const MachOFormat::Section *Section = getSection64(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI); Result = Entry->Value; if (Entry->SectionIndex) { - const MachOFormat::Section *Section = + const MachOFormat::Section *Section = getSection(Sections[Entry->SectionIndex-1]); Result += Section->Offset - Section->Address; } @@ -216,10 +221,12 @@ error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, uint64_t &Result) const { if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(DRI); Result = Entry->Value; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI); Result = Entry->Value; } return object_error::success; @@ -232,7 +239,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t EndOffset = 0; uint8_t SectionIndex; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(DRI); BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { @@ -259,7 +267,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, DRI.d.b++; } } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI); BeginOffset = Entry->Value; SectionIndex = Entry->SectionIndex; if (!SectionIndex) { @@ -300,11 +309,13 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, char &Result) const { uint8_t Type, Flags; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(DRI); Type = Entry->Type; Flags = Entry->Flags; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI); Type = Entry->Type; Flags = Entry->Flags; } @@ -334,11 +345,13 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, uint16_t MachOFlags; uint8_t MachOType; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(DRI); MachOFlags = Entry->Flags; MachOType = Entry->Type; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(DRI); MachOFlags = Entry->Flags; MachOType = Entry->Type; } @@ -371,10 +384,12 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { uint8_t index; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(Symb); index = Entry->SectionIndex; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(Symb); index = Entry->SectionIndex; } @@ -390,10 +405,12 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const { uint8_t n_type; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(Symb); n_type = Entry->Type; } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(Symb); n_type = Entry->Type; } Res = SymbolRef::ST_Other; @@ -465,14 +482,14 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { while (DRI.d.a < LoadCommandCount) { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Segment) { - const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = - reinterpret_cast(Command); + const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = + reinterpret_cast*>(Command); if (DRI.d.b < SegmentLoadCmd->NumSections) return; } else if (Command->Type == macho::LCT_Segment64) { - const MachOFormat::Segment64LoadCommand *Segment64LoadCmd = - reinterpret_cast(Command); - if (DRI.d.b < Segment64LoadCmd->NumSections) + const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = + reinterpret_cast*>(Command); + if (DRI.d.b < SegmentLoadCmd->NumSections) return; } @@ -489,13 +506,14 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, return object_error::success; } -const MachOFormat::Section *MachOObjectFile::getSection(DataRefImpl DRI) const { +const MachOFormat::Section * +MachOObjectFile::getSection(DataRefImpl DRI) const { assert(!is64Bit()); const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast(Command); uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) + - DRI.d.b * sizeof(MachOFormat::Section); - return reinterpret_cast(SectionAddr); + DRI.d.b * sizeof(MachOFormat::Section); + return reinterpret_cast*>(SectionAddr); } std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { @@ -505,14 +523,14 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -const MachOFormat::Section64 * +const MachOFormat::Section * MachOObjectFile::getSection64(DataRefImpl DRI) const { assert(is64Bit()); const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast(Command); uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) + - DRI.d.b * sizeof(MachOFormat::Section64); - return reinterpret_cast(SectionAddr); + DRI.d.b * sizeof(MachOFormat::Section); + return reinterpret_cast*>(SectionAddr); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -525,10 +543,10 @@ static StringRef parseSegmentOrSectionName(const char *P) { ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { if (is64Bit()) { - const MachOFormat::Section64 *sec = getSection64(DRI); + const MachOFormat::Section *sec = getSection64(DRI); return ArrayRef(sec->Name); } else { - const MachOFormat::Section *sec = getSection(DRI); + const MachOFormat::Section *sec = getSection(DRI); return ArrayRef(sec->Name); } } @@ -543,10 +561,10 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { if (is64Bit()) { - const MachOFormat::Section64 *sec = getSection64(Sec); + const MachOFormat::Section *sec = getSection64(Sec); return ArrayRef(sec->SegmentName, 16); } else { - const MachOFormat::Section *sec = getSection(Sec); + const MachOFormat::Section *sec = getSection(Sec); return ArrayRef(sec->SegmentName); } } @@ -559,10 +577,10 @@ StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, uint64_t &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); Result = Sect->Address; } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Address; } return object_error::success; @@ -571,10 +589,10 @@ error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, uint64_t &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); Result = Sect->Size; } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Size; } return object_error::success; @@ -583,10 +601,10 @@ error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, StringRef &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); Result = getData(Sect->Offset, Sect->Size); } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = getData(Sect->Offset, Sect->Size); } return object_error::success; @@ -595,10 +613,10 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, uint64_t &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); Result = uint64_t(1) << Sect->Align; } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = uint64_t(1) << Sect->Align; } return object_error::success; @@ -607,10 +625,10 @@ error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, error_code MachOObjectFile::isSectionText(DataRefImpl DRI, bool &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); Result = Sect->Flags & macho::SF_PureInstructions; } return object_error::success; @@ -647,12 +665,12 @@ error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, bool &Result) const { if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(DRI); + const MachOFormat::Section *Sect = getSection64(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); } else { - const MachOFormat::Section *Sect = getSection(DRI); + const MachOFormat::Section *Sect = getSection(DRI); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Result = (SectionType == MachO::SectionTypeZeroFill || SectionType == MachO::SectionTypeZeroFillLarge); @@ -688,11 +706,13 @@ error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, SectEnd += SectBegin; if (is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = getSymbol64TableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbol64TableEntry(Symb); uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } else { - const MachOFormat::SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + const MachOFormat::SymbolTableEntry *Entry = + getSymbolTableEntry(Symb); uint64_t SymAddr= Entry->Value; Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); } @@ -705,13 +725,14 @@ relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { ret.d.b = getSectionIndex(Sec); return relocation_iterator(RelocationRef(ret, this)); } + relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t last_reloc; if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(Sec); + const MachOFormat::Section *Sect = getSection64(Sec); last_reloc = Sect->NumRelocationTableEntries; } else { - const MachOFormat::Section *Sect = getSection(Sec); + const MachOFormat::Section *Sect = getSection(Sec); last_reloc = Sect->NumRelocationTableEntries; } DataRefImpl ret; @@ -738,10 +759,10 @@ const MachOFormat::RelocationEntry * MachOObjectFile::getRelocation(DataRefImpl Rel) const { uint32_t relOffset; if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); relOffset = Sect->RelocationTableOffset; } uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); @@ -759,10 +780,10 @@ error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { const uint8_t* sectAddress = 0; if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Address; } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Address; } const MachOFormat::RelocationEntry *RE = getRelocation(Rel); @@ -926,10 +947,10 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, if (!isExtern) { const uint8_t* sectAddress = base(); if (is64Bit()) { - const MachOFormat::Section64 *Sect = getSection64(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); sectAddress += Sect->Offset; } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); + const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); sectAddress += Sect->Offset; } Res = reinterpret_cast(sectAddress); diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 190baa229b..89402808bf 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -161,7 +161,7 @@ static void getSection(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSection &Section) { if (Obj->is64Bit()) { - const MachOFormat::Section64 *Sect = Obj->getSection64(DRI); + const MachOFormat::Section *Sect = Obj->getSection64(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -173,7 +173,7 @@ static void getSection(const MachOObjectFile *Obj, Section.Reserved1 = Sect->Reserved1; Section.Reserved2 = Sect->Reserved2; } else { - const MachOFormat::Section *Sect = Obj->getSection(DRI); + const MachOFormat::Section *Sect = Obj->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -191,15 +191,16 @@ static void getSymbol(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { if (Obj->is64Bit()) { - const MachOFormat::Symbol64TableEntry *Entry = - Obj->getSymbol64TableEntry( DRI); + const MachOFormat::SymbolTableEntry *Entry = + Obj->getSymbol64TableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; Symbol.Flags = Entry->Flags; Symbol.Value = Entry->Value; } else { - const MachOFormat::SymbolTableEntry *Entry = Obj->getSymbolTableEntry(DRI); + const MachOFormat::SymbolTableEntry *Entry = + Obj->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; -- cgit v1.2.3-70-g09d2 From 3388589fc102b873ee9b73ffdab0f532ee3ceda6 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 8 Apr 2013 23:57:13 +0000 Subject: Add a SectionBase struct. Use it to share code and when we don't need to know if we have a 32 or 64 bit Section. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179072 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 6 ++++++ lib/Object/MachOObjectFile.cpp | 48 +++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 24 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 5c50ceb2b6..07c8fc5ca2 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -27,6 +27,11 @@ namespace llvm { namespace object { namespace MachOFormat { + struct SectionBase { + char Name[16]; + char SegmentName[16]; + }; + template struct Section; @@ -254,6 +259,7 @@ private: typedef SmallVector SectionList; SectionList Sections; + const MachOFormat::SectionBase *getSectionBase(DataRefImpl DRI) const; void moveToNextSection(DataRefImpl &DRI) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 30ab00f450..3931c53ac8 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -509,11 +509,8 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, const MachOFormat::Section * MachOObjectFile::getSection(DataRefImpl DRI) const { assert(!is64Bit()); - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - uintptr_t CommandAddr = reinterpret_cast(Command); - uintptr_t SectionAddr = CommandAddr + sizeof(macho::SegmentLoadCommand) + - DRI.d.b * sizeof(MachOFormat::Section); - return reinterpret_cast*>(SectionAddr); + const MachOFormat::SectionBase *Addr = getSectionBase(DRI); + return reinterpret_cast*>(Addr); } std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { @@ -523,14 +520,27 @@ std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } +const MachOFormat::SectionBase* +MachOObjectFile::getSectionBase(DataRefImpl DRI) const { + const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + uintptr_t CommandAddr = reinterpret_cast(Command); + + bool Is64 = is64Bit(); + unsigned SegmentLoadSize = + Is64 ? sizeof(MachOFormat::SegmentLoadCommand) : + sizeof(MachOFormat::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section) : + sizeof(MachOFormat::Section); + + uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; + return reinterpret_cast(SectionAddr); +} + const MachOFormat::Section * MachOObjectFile::getSection64(DataRefImpl DRI) const { assert(is64Bit()); - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - uintptr_t CommandAddr = reinterpret_cast(Command); - uintptr_t SectionAddr = CommandAddr + sizeof(macho::Segment64LoadCommand) + - DRI.d.b * sizeof(MachOFormat::Section); - return reinterpret_cast*>(SectionAddr); + const MachOFormat::SectionBase *Addr = getSectionBase(DRI); + return reinterpret_cast*>(Addr); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -542,13 +552,8 @@ static StringRef parseSegmentOrSectionName(const char *P) { } ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { - if (is64Bit()) { - const MachOFormat::Section *sec = getSection64(DRI); - return ArrayRef(sec->Name); - } else { - const MachOFormat::Section *sec = getSection(DRI); - return ArrayRef(sec->Name); - } + const MachOFormat::SectionBase *Base = getSectionBase(DRI); + return ArrayRef(Base->Name); } error_code MachOObjectFile::getSectionName(DataRefImpl DRI, @@ -560,13 +565,8 @@ error_code MachOObjectFile::getSectionName(DataRefImpl DRI, ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - if (is64Bit()) { - const MachOFormat::Section *sec = getSection64(Sec); - return ArrayRef(sec->SegmentName, 16); - } else { - const MachOFormat::Section *sec = getSection(Sec); - return ArrayRef(sec->SegmentName); - } + const MachOFormat::SectionBase *Base = getSectionBase(Sec); + return ArrayRef(Base->SegmentName); } StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { -- cgit v1.2.3-70-g09d2 From 7df9c57651574feccd53aec0aac469dea2b48bc6 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 9 Apr 2013 00:22:58 +0000 Subject: Add a SymbolTableEntryBase. Use it when we don't need to know if we have a 32 or 64 bit SymbolTableEntry. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179074 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 16 ++++++--- lib/Object/MachOObjectFile.cpp | 74 +++++++++++++++--------------------------- 2 files changed, 38 insertions(+), 52 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 07c8fc5ca2..8c2e268dae 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -71,6 +71,13 @@ namespace MachOFormat { support::ulittle32_t Word1; }; + struct SymbolTableEntryBase { + support::ulittle32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + support::ulittle16_t Flags; + }; + template struct SymbolTableEntry; @@ -263,12 +270,11 @@ private: void moveToNextSection(DataRefImpl &DRI) const; - const MachOFormat::SymbolTableEntry * - getSymbolTableEntry(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; + const MachOFormat::SymbolTableEntryBase * + getSymbolTableEntryBase(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry * - getSymbol64TableEntry(DataRefImpl DRI, + const MachOFormat::SymbolTableEntryBase * + getSymbolTableEntryBase(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; void moveToNextSymbol(DataRefImpl &DRI) const; diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 3931c53ac8..ae30105a93 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -116,47 +116,40 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { } } -const MachOFormat::SymbolTableEntry * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { +const MachOFormat::SymbolTableEntryBase * +MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI) const { const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = reinterpret_cast(Command); - - return getSymbolTableEntry(DRI, SymtabLoadCmd); + return getSymbolTableEntryBase(DRI, SymtabLoadCmd); } const MachOFormat::SymbolTableEntry * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI, +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { + const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + return reinterpret_cast*>(Base); +} + +const MachOFormat::SymbolTableEntryBase * +MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI, const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; - uint64_t Offset = (SymbolTableOffset + - Index * sizeof(MachOFormat::SymbolTableEntry)); - StringRef Data = - getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); - return - reinterpret_cast*>(Data.data()); -} -const MachOFormat::SymbolTableEntry* -MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(MachOFormat::SymbolTableEntry) : + sizeof(MachOFormat::SymbolTableEntry); - return getSymbol64TableEntry(DRI, SymtabLoadCmd); + uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; + StringRef Data = getData(Offset, SymbolTableEntrySize); + return + reinterpret_cast(Data.data()); } const MachOFormat::SymbolTableEntry* -MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { - uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; - unsigned Index = DRI.d.b; - uint64_t Offset = (SymbolTableOffset + - Index * sizeof(MachOFormat::SymbolTableEntry)); - StringRef Data = getData(Offset, sizeof(MachOFormat::SymbolTableEntry)); - return - reinterpret_cast*>(Data.data()); +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { + const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + return reinterpret_cast*>(Base); } error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, @@ -176,16 +169,9 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, SymtabLoadCmd->StringTableSize); - uint32_t StringIndex; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI, SymtabLoadCmd); - StringIndex = Entry->StringIndex; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI, SymtabLoadCmd); - StringIndex = Entry->StringIndex; - } + const MachOFormat::SymbolTableEntryBase *Entry = + getSymbolTableEntryBase(DRI, SymtabLoadCmd); + uint32_t StringIndex = Entry->StringIndex; const char *Start = &StringTable.data()[StringIndex]; Result = StringRef(Start); @@ -403,16 +389,10 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const { - uint8_t n_type; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(Symb); - n_type = Entry->Type; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(Symb); - n_type = Entry->Type; - } + const MachOFormat::SymbolTableEntryBase *Entry = + getSymbolTableEntryBase(Symb); + uint8_t n_type = Entry->Type; + Res = SymbolRef::ST_Other; // If this is a STAB debugging symbol, we can do nothing more. -- cgit v1.2.3-70-g09d2 From 8faf7df1447ca6ea4a3ff8f82789923d1839fb54 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 9 Apr 2013 01:04:06 +0000 Subject: More uses for SymbolTableEntryBase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179076 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 44 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 35 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index ae30105a93..e1eec36598 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -293,18 +293,9 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, char &Result) const { - uint8_t Type, Flags; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI); - Type = Entry->Type; - Flags = Entry->Flags; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI); - Type = Entry->Type; - Flags = Entry->Flags; - } + const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); + uint8_t Type = Entry->Type; + uint16_t Flags = Entry->Flags; char Char; switch (Type & macho::STF_TypeMask) { @@ -328,19 +319,9 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, uint32_t &Result) const { - uint16_t MachOFlags; - uint8_t MachOType; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI); - MachOFlags = Entry->Flags; - MachOType = Entry->Type; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI); - MachOFlags = Entry->Flags; - MachOType = Entry->Type; - } + const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); + uint8_t MachOType = Entry->Type; + uint16_t MachOFlags = Entry->Flags; // TODO: Correctly set SF_ThreadLocal Result = SymbolRef::SF_None; @@ -368,16 +349,9 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { - uint8_t index; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(Symb); - index = Entry->SectionIndex; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(Symb); - index = Entry->SectionIndex; - } + const MachOFormat::SymbolTableEntryBase *Entry = + getSymbolTableEntryBase(Symb); + uint8_t index = Entry->SectionIndex; if (index == 0) Res = end_sections(); -- cgit v1.2.3-70-g09d2 From f6cfc15705140cc958b784a1bc98f7f0f09be6be Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 9 Apr 2013 14:49:08 +0000 Subject: Convert MachOObjectFile to a template. For now it is templated only on being 64 or 32 bits. I will add little/big endian next. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179097 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 802 ++++++++++++++++++++++++-- lib/Object/MachOObjectFile.cpp | 962 ++++---------------------------- tools/llvm-objdump/MachODump.cpp | 8 +- tools/llvm-objdump/llvm-objdump.cpp | 4 +- tools/llvm-readobj/MachODumper.cpp | 28 +- tools/llvm-symbolizer/LLVMSymbolize.cpp | 2 +- 6 files changed, 881 insertions(+), 925 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8c2e268dae..384e9ad4ef 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOObject.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Endian.h" @@ -164,9 +165,16 @@ namespace MachOFormat { }; } -class MachOObjectFile : public ObjectFile { +class MachOObjectFileBase : public ObjectFile { public: - MachOObjectFile(MemoryBuffer *Object, bool Is64bits, error_code &ec); + typedef MachOFormat::SymbolTableEntryBase SymbolTableEntryBase; + typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; + typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::SectionBase SectionBase; + typedef MachOFormat::LoadCommand LoadCommand; + typedef MachOFormat::Header Header; + + MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); virtual symbol_iterator begin_symbols() const; virtual symbol_iterator end_symbols() const; @@ -174,7 +182,6 @@ public: virtual symbol_iterator end_dynamic_symbols() const; virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual section_iterator begin_sections() const; virtual section_iterator end_sections() const; virtual uint8_t getBytesInAddress() const; @@ -192,16 +199,10 @@ public: ArrayRef getSectionRawName(DataRefImpl Sec) const; ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; - const MachOFormat::Section *getSection64(DataRefImpl DRI) const; - const MachOFormat::Section *getSection(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry * - getSymbol64TableEntry(DataRefImpl DRI) const; - const MachOFormat::SymbolTableEntry * - getSymbolTableEntry(DataRefImpl DRI) const; bool is64Bit() const; - const MachOFormat::LoadCommand *getLoadCommandInfo(unsigned Index) const; + const LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - const MachOFormat::Header *getHeader() const; + const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; @@ -212,79 +213,774 @@ public: protected: virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; - virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl DRI, DataRefImpl S, - bool &Result) const; virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; virtual error_code getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const; - virtual error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const; - virtual error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const; - virtual error_code getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - virtual error_code getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const; - virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; -private: + std::size_t getSectionIndex(DataRefImpl Sec) const; + typedef SmallVector SectionList; SectionList Sections; - const MachOFormat::SectionBase *getSectionBase(DataRefImpl DRI) const; + void moveToNextSymbol(DataRefImpl &DRI) const; + void printRelocationTargetName(const RelocationEntry *RE, + raw_string_ostream &fmt) const; + const SectionBase *getSectionBase(DataRefImpl DRI) const; + const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; - void moveToNextSection(DataRefImpl &DRI) const; +private: - const MachOFormat::SymbolTableEntryBase * - getSymbolTableEntryBase(DataRefImpl DRI) const; + const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, + const SymtabLoadCommand *SymtabLoadCmd) const; +}; - const MachOFormat::SymbolTableEntryBase * - getSymbolTableEntryBase(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const; +template +struct MachOObjectFileHelperCommon { + typedef MachOFormat::SegmentLoadCommand SegmentLoadCommand; + typedef MachOFormat::SymbolTableEntry SymbolTableEntry; + typedef MachOFormat::Section Section; +}; - void moveToNextSymbol(DataRefImpl &DRI) const; - const MachOFormat::RelocationEntry *getRelocation(DataRefImpl Rel) const; - std::size_t getSectionIndex(DataRefImpl Sec) const; +template +struct MachOObjectFileHelper; - void printRelocationTargetName(const MachOFormat::RelocationEntry *RE, - raw_string_ostream &fmt) const; +template<> +struct MachOObjectFileHelper : + public MachOObjectFileHelperCommon { + static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; +}; + +template<> +struct MachOObjectFileHelper : + public MachOObjectFileHelperCommon { + static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; +}; + +template +class MachOObjectFile : public MachOObjectFileBase { +public: + static const macho::LoadCommandType SegmentLoadType = + MachOObjectFileHelper::SegmentLoadType; + typedef typename MachOObjectFileHelper::SegmentLoadCommand + SegmentLoadCommand; + typedef typename MachOObjectFileHelper::SymbolTableEntry + SymbolTableEntry; + typedef typename MachOObjectFileHelper::Section Section; + + MachOObjectFile(MemoryBuffer *Object, error_code &ec) : + MachOObjectFileBase(Object, is64Bits, ec) { + DataRefImpl DRI; + moveToNextSection(DRI); + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + Sections.push_back(DRI); + DRI.d.b++; + moveToNextSection(DRI); + } + } + + static inline bool classof(const Binary *v) { + return v->getType() == getMachOType(true, is64Bits); + } + + const Section *getSection(DataRefImpl DRI) const; + const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + + virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; + virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; + virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; + virtual error_code getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const; + virtual error_code getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const; + virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual section_iterator begin_sections() const; + void moveToNextSection(DataRefImpl &DRI) const; }; +template +const typename MachOObjectFile::Section * +MachOObjectFile::getSection(DataRefImpl DRI) const { + const SectionBase *Addr = getSectionBase(DRI); + return reinterpret_cast(Addr); +} + +template +const typename MachOObjectFile::SymbolTableEntry * +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { + const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + return reinterpret_cast(Base); +} + +template +const typename MachOObjectFile::RelocationEntry * +MachOObjectFile::getRelocation(DataRefImpl Rel) const { + const Section *Sect = getSection(Sections[Rel.d.b]); + uint32_t RelOffset = Sect->RelocationTableOffset; + uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); + StringRef Data = getData(Offset, sizeof(RelocationEntry)); + return reinterpret_cast(Data.data()); +} + +template +error_code +MachOObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Address; + return object_error::success; +} + +template +error_code +MachOObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Size; + return object_error::success; +} + +template +error_code +MachOObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { + const Section *Sect = getSection(Sec); + Res = getData(Sect->Offset, Sect->Size); + return object_error::success; +} + +template +error_code +MachOObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { + const Section *Sect = getSection(Sec); + Res = uint64_t(1) << Sect->Align; + return object_error::success; +} + +template +error_code +MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { + const Section *Sect = getSection(Sec); + Res = Sect->Flags & macho::SF_PureInstructions; + return object_error::success; +} + +template +error_code +MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { + const Section *Sect = getSection(Sec); + unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; + Res = SectionType == MachO::SectionTypeZeroFill || + SectionType == MachO::SectionTypeZeroFillLarge; + return object_error::success; +} + +template +relocation_iterator +MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { + const Section *Sect = getSection(Sec); + uint32_t LastReloc = Sect->NumRelocationTableEntries; + DataRefImpl Ret; + Ret.d.a = LastReloc; + Ret.d.b = getSectionIndex(Sec); + return relocation_iterator(RelocationRef(Ret, this)); +} + +template +error_code +MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + const Section *Sect = getSection(Sections[Rel.d.b]); + uint64_t SectAddress = Sect->Address; + const RelocationEntry *RE = getRelocation(Rel); + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + uint64_t RelAddr; + if (isScattered) + RelAddr = RE->Word0 & 0xFFFFFF; + else + RelAddr = RE->Word0; + + Res = SectAddress + RelAddr; + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + if (isScattered) + Res = RE->Word0 & 0xFFFFFF; + else + Res = RE->Word0; + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + uint32_t SymbolIdx = RE->Word1 & 0xffffff; + bool isExtern = (RE->Word1 >> 27) & 1; + + DataRefImpl Sym; + moveToNextSymbol(Sym); + if (isExtern) { + for (unsigned i = 0; i < SymbolIdx; i++) { + Sym.d.b++; + moveToNextSymbol(Sym); + assert(Sym.d.a < getHeader()->NumLoadCommands && + "Relocation symbol index out of range!"); + } + } + Res = SymbolRef(Sym, this); + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + bool isExtern = (RE->Word1 >> 27) & 1; + Res = 0; + if (!isExtern) { + const uint8_t* sectAddress = base(); + const Section *Sect = getSection(Sections[Rel.d.b]); + sectAddress += Sect->Offset; + Res = reinterpret_cast(sectAddress); + } + return object_error::success; +} + +template +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { + const RelocationEntry *RE = getRelocation(Rel); + Res = RE->Word0; + Res <<= 32; + Res |= RE->Word1; + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + // TODO: Support scattered relocations. + StringRef res; + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + unsigned r_type; + if (isScattered) + r_type = (RE->Word0 >> 24) & 0xF; + else + r_type = (RE->Word1 >> 28) & 0xF; + + switch (Arch) { + case Triple::x86: { + static const char *const Table[] = { + "GENERIC_RELOC_VANILLA", + "GENERIC_RELOC_PAIR", + "GENERIC_RELOC_SECTDIFF", + "GENERIC_RELOC_PB_LA_PTR", + "GENERIC_RELOC_LOCAL_SECTDIFF", + "GENERIC_RELOC_TLV" }; + + if (r_type > 6) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::x86_64: { + static const char *const Table[] = { + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SUBTRACTOR", + "X86_64_RELOC_SIGNED_1", + "X86_64_RELOC_SIGNED_2", + "X86_64_RELOC_SIGNED_4", + "X86_64_RELOC_TLV" }; + + if (r_type > 9) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::arm: { + static const char *const Table[] = { + "ARM_RELOC_VANILLA", + "ARM_RELOC_PAIR", + "ARM_RELOC_SECTDIFF", + "ARM_RELOC_LOCAL_SECTDIFF", + "ARM_RELOC_PB_LA_PTR", + "ARM_RELOC_BR24", + "ARM_THUMB_RELOC_BR22", + "ARM_THUMB_32BIT_BRANCH", + "ARM_RELOC_HALF", + "ARM_RELOC_HALF_SECTDIFF" }; + + if (r_type > 9) + res = "Unknown"; + else + res = Table[r_type]; + break; + } + case Triple::ppc: { + static const char *const Table[] = { + "PPC_RELOC_VANILLA", + "PPC_RELOC_PAIR", + "PPC_RELOC_BR14", + "PPC_RELOC_BR24", + "PPC_RELOC_HI16", + "PPC_RELOC_LO16", + "PPC_RELOC_HA16", + "PPC_RELOC_LO14", + "PPC_RELOC_SECTDIFF", + "PPC_RELOC_PB_LA_PTR", + "PPC_RELOC_HI16_SECTDIFF", + "PPC_RELOC_LO16_SECTDIFF", + "PPC_RELOC_HA16_SECTDIFF", + "PPC_RELOC_JBSR", + "PPC_RELOC_LO14_SECTDIFF", + "PPC_RELOC_LOCAL_SECTDIFF" }; + + res = Table[r_type]; + break; + } + case Triple::UnknownArch: + res = "Unknown"; + break; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; + + bool isPCRel; + if (isScattered) + isPCRel = ((RE->Word0 >> 30) & 1); + else + isPCRel = ((RE->Word1 >> 24) & 1); + + // Determine any addends that should be displayed with the relocation. + // These require decoding the relocation type, which is triple-specific. + + // X86_64 has entirely custom relocation types. + if (Arch == Triple::x86_64) { + bool isPCRel = ((RE->Word1 >> 24) & 1); + + switch (Type) { + case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD + case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT + printRelocationTargetName(RE, fmt); + fmt << "@GOT"; + if (isPCRel) fmt << "PCREL"; + break; + } + case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86_64_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 0) + report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol, + // X86_64_SUBTRACTOR contains to the subtrahend. + printRelocationTargetName(RENext, fmt); + fmt << "-"; + printRelocationTargetName(RE, fmt); + break; + } + case macho::RIT_X86_64_TLV: + printRelocationTargetName(RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 + printRelocationTargetName(RE, fmt); + fmt << "-1"; + break; + case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 + printRelocationTargetName(RE, fmt); + fmt << "-2"; + break; + case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 + printRelocationTargetName(RE, fmt); + fmt << "-4"; + break; + default: + printRelocationTargetName(RE, fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm) { + // Generic relocation types... + switch (Type) { + case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info + return object_error::success; + case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(RE, fmt); + fmt << "-"; + printRelocationTargetName(RENext, fmt); + break; + } + } + + if (Arch == Triple::x86) { + // All X86 relocations that need special printing were already + // handled in the generic code. + switch (Type) { + case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(RE, fmt); + fmt << "-"; + printRelocationTargetName(RENext, fmt); + break; + } + case macho::RIT_Generic_TLV: { + printRelocationTargetName(RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + } + default: + printRelocationTargetName(RE, fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case macho::RIT_ARM_Half: // ARM_RELOC_HALF + case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF + // Half relocations steal a bit from the length field to encode + // whether this is an upper16 or a lower16 relocation. + bool isUpper; + if (isScattered) + isUpper = (RE->Word0 >> 28) & 1; + else + isUpper = (RE->Word1 >> 25) & 1; + + if (isUpper) + fmt << ":upper16:("; + else + fmt << ":lower16:("; + printRelocationTargetName(RE, fmt); + + DataRefImpl RelNext = Rel; + RelNext.d.a++; + const RelocationEntry *RENext = getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + bool isNextScattered = (Arch != Triple::x86_64) && + (RENext->Word0 & macho::RF_Scattered); + unsigned RType; + if (isNextScattered) + RType = (RENext->Word0 >> 24) & 0xF; + else + RType = (RENext->Word1 >> 28) & 0xF; + + if (RType != 1) + report_fatal_error("Expected ARM_RELOC_PAIR after " + "GENERIC_RELOC_HALF"); + + // NOTE: The half of the target virtual address is stashed in the + // address field of the secondary relocation, but we can't reverse + // engineer the constant offset from it without decoding the movw/movt + // instruction to find the other half in its immediate field. + + // ARM_RELOC_HALF_SECTDIFF encodes the second section in the + // symbol/section pointer of the follow-on relocation. + if (Type == macho::RIT_ARM_HalfDifference) { + fmt << "-"; + printRelocationTargetName(RENext, fmt); + } + + fmt << ")"; + break; + } + default: { + printRelocationTargetName(RE, fmt); + } + } + } + } else + printRelocationTargetName(RE, fmt); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + return object_error::success; +} + +template +error_code +MachOObjectFile::getRelocationHidden(DataRefImpl Rel, + bool &Result) const { + const RelocationEntry *RE = getRelocation(Rel); + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; + + Result = false; + + // On arches that use the generic relocations, GENERIC_RELOC_PAIR + // is always hidden. + if (Arch == Triple::x86 || Arch == Triple::arm) { + if (Type == macho::RIT_Pair) Result = true; + } else if (Arch == Triple::x86_64) { + // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows + // an X864_64_RELOC_SUBTRACTOR. + if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { + DataRefImpl RelPrev = Rel; + RelPrev.d.a--; + const RelocationEntry *REPrev = getRelocation(RelPrev); + + unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + + if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; + } + } + + return object_error::success; +} + +template +error_code +MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Res) const { + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + Res = Entry->Value; + if (Entry->SectionIndex) { + const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); + Res += Sec->Offset - Sec->Address; + } + + return object_error::success; +} + +template +error_code +MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + SymbolRef::Type ST; + getSymbolType(Symb, ST); + if (ST == SymbolRef::ST_Unknown) { + Result = false; + return object_error::success; + } + + uint64_t SectBegin, SectEnd; + getSectionAddress(Sec, SectBegin); + getSectionSize(Sec, SectEnd); + SectEnd += SectBegin; + + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + uint64_t SymAddr= Entry->Value; + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); + + return object_error::success; +} + +template +error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const { + const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); + Res = Entry->Value; + return object_error::success; +} + +template +error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint64_t BeginOffset; + uint64_t EndOffset = 0; + uint8_t SectionIndex; + + const SymbolTableEntry *Entry = getSymbolTableEntry(DRI); + BeginOffset = Entry->Value; + SectionIndex = Entry->SectionIndex; + if (!SectionIndex) { + uint32_t flags = SymbolRef::SF_None; + getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Entry->Value; + else + Result = UnknownAddressOrSize; + return object_error::success; + } + // Unfortunately symbols are unsorted so we need to touch all + // symbols from load command + DRI.d.b = 0; + uint32_t Command = DRI.d.a; + while (Command == DRI.d.a) { + moveToNextSymbol(DRI); + if (DRI.d.a < LoadCommandCount) { + Entry = getSymbolTableEntry(DRI); + if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) + if (!EndOffset || Entry->Value < EndOffset) + EndOffset = Entry->Value; + } + DRI.d.b++; + } + if (!EndOffset) { + uint64_t Size; + getSectionSize(Sections[SectionIndex-1], Size); + getSectionAddress(Sections[SectionIndex-1], EndOffset); + EndOffset += Size; + } + Result = EndOffset - BeginOffset; + return object_error::success; +} + +template +error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Res) const { + Sec.d.b++; + moveToNextSection(Sec); + Res = SectionRef(Sec, this); + return object_error::success; +} + +template +section_iterator MachOObjectFile::begin_sections() const { + DataRefImpl DRI; + moveToNextSection(DRI); + return section_iterator(SectionRef(DRI, this)); +} + +template +void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + if (Command->Type == SegmentLoadType) { + const SegmentLoadCommand *SegmentLoadCmd = + reinterpret_cast(Command); + if (DRI.d.b < SegmentLoadCmd->NumSections) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e1eec36598..20b66d94e8 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -15,6 +15,7 @@ #include "llvm/Object/MachO.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" #include "llvm/Support/MemoryBuffer.h" @@ -28,34 +29,25 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool Is64bits, - error_code &ec) +MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, + error_code &ec) : ObjectFile(getMachOType(true, Is64bits), Object) { - DataRefImpl DRI; - moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - Sections.push_back(DRI); - DRI.d.b++; - moveToNextSection(DRI); - } } -bool MachOObjectFile::is64Bit() const { - unsigned int Type = getType(); - return Type == ID_MachO64L || Type == ID_MachO64B; +bool MachOObjectFileBase::is64Bit() const { + return isa >(this); } -const MachOFormat::LoadCommand * -MachOObjectFile::getLoadCommandInfo(unsigned Index) const { +const MachOObjectFileBase::LoadCommand * +MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const { uint64_t Offset; uint64_t NewOffset = getHeaderSize(); - const MachOFormat::LoadCommand *Load; + const LoadCommand *Load; unsigned I = 0; do { Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(MachOFormat::LoadCommand)); - Load = reinterpret_cast(Data.data()); + StringRef Data = getData(Offset, sizeof(LoadCommand)); + Load = reinterpret_cast(Data.data()); NewOffset = Offset + Load->Size; ++I; } while (I != Index + 1); @@ -63,8 +55,8 @@ MachOObjectFile::getLoadCommandInfo(unsigned Index) const { return Load; } -void MachOObjectFile::ReadULEB128s(uint64_t Index, - SmallVectorImpl &Out) const { +void MachOObjectFileBase::ReadULEB128s(uint64_t Index, + SmallVectorImpl &Out) const { DataExtractor extractor(ObjectFile::getData(), true, 0); uint32_t offset = Index; @@ -75,16 +67,16 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -const MachOFormat::Header *MachOObjectFile::getHeader() const { - StringRef Data = getData(0, sizeof(MachOFormat::Header)); - return reinterpret_cast(Data.data()); +const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const { + StringRef Data = getData(0, sizeof(Header)); + return reinterpret_cast(Data.data()); } -unsigned MachOObjectFile::getHeaderSize() const { +unsigned MachOObjectFileBase::getHeaderSize() const { return is64Bit() ? macho::Header64Size : macho::Header32Size; } -StringRef MachOObjectFile::getData(size_t Offset, size_t Size) const { +StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } @@ -92,7 +84,11 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; - ObjectFile *Ret = new MachOObjectFile(Buffer, Is64Bits, ec); + ObjectFile *Ret; + if (Is64Bits) + Ret = new MachOObjectFile(Buffer, ec); + else + Ret = new MachOObjectFile(Buffer, ec); if (ec) return NULL; return Ret; @@ -100,13 +96,13 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { +void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const { uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); if (Command->Type == macho::LCT_Symtab) { - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast(Command); if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) return; } @@ -116,23 +112,17 @@ void MachOObjectFile::moveToNextSymbol(DataRefImpl &DRI) const { } } -const MachOFormat::SymbolTableEntryBase * -MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); +const MachOObjectFileBase::SymbolTableEntryBase * +MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast(Command); return getSymbolTableEntryBase(DRI, SymtabLoadCmd); } -const MachOFormat::SymbolTableEntry * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); - return reinterpret_cast*>(Base); -} - -const MachOFormat::SymbolTableEntryBase * -MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI, - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd) const { +const MachOObjectFileBase::SymbolTableEntryBase * +MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, + const SymtabLoadCommand *SymtabLoadCmd) const { uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; unsigned Index = DRI.d.b; @@ -142,34 +132,27 @@ MachOObjectFile::getSymbolTableEntryBase(DataRefImpl DRI, uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; StringRef Data = getData(Offset, SymbolTableEntrySize); - return - reinterpret_cast(Data.data()); + return reinterpret_cast(Data.data()); } -const MachOFormat::SymbolTableEntry* -MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - const MachOFormat::SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); - return reinterpret_cast*>(Base); -} - -error_code MachOObjectFile::getSymbolNext(DataRefImpl DRI, - SymbolRef &Result) const { +error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI, + SymbolRef &Result) const { DRI.d.b++; moveToNextSymbol(DRI); Result = SymbolRef(DRI, this); return object_error::success; } -error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, - StringRef &Result) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const MachOFormat::SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); +error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI, + StringRef &Result) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *SymtabLoadCmd = + reinterpret_cast(Command); StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, SymtabLoadCmd->StringTableSize); - const MachOFormat::SymbolTableEntryBase *Entry = + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI, SymtabLoadCmd); uint32_t StringIndex = Entry->StringIndex; @@ -179,121 +162,9 @@ error_code MachOObjectFile::getSymbolName(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolFileOffset(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI); - Result = Entry->Value; - if (Entry->SectionIndex) { - const MachOFormat::Section *Section = - getSection64(Sections[Entry->SectionIndex-1]); - Result += Section->Offset - Section->Address; - } - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI); - Result = Entry->Value; - if (Entry->SectionIndex) { - const MachOFormat::Section *Section = - getSection(Sections[Entry->SectionIndex-1]); - Result += Section->Offset - Section->Address; - } - } - - return object_error::success; -} - -error_code MachOObjectFile::getSymbolAddress(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI); - Result = Entry->Value; - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI); - Result = Entry->Value; - } - return object_error::success; -} - -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, - uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - uint64_t BeginOffset; - uint64_t EndOffset = 0; - uint8_t SectionIndex; - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(DRI); - BeginOffset = Entry->Value; - SectionIndex = Entry->SectionIndex; - if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); - if (flags & SymbolRef::SF_Common) - Result = Entry->Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - DRI.d.b = 0; - uint32_t Command = DRI.d.a; - while (Command == DRI.d.a) { - moveToNextSymbol(DRI); - if (DRI.d.a < LoadCommandCount) { - Entry = getSymbol64TableEntry(DRI); - if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) - if (!EndOffset || Entry->Value < EndOffset) - EndOffset = Entry->Value; - } - DRI.d.b++; - } - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(DRI); - BeginOffset = Entry->Value; - SectionIndex = Entry->SectionIndex; - if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); - if (flags & SymbolRef::SF_Common) - Result = Entry->Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - DRI.d.b = 0; - uint32_t Command = DRI.d.a; - while (Command == DRI.d.a) { - moveToNextSymbol(DRI); - if (DRI.d.a < LoadCommandCount) { - Entry = getSymbolTableEntry(DRI); - if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) - if (!EndOffset || Entry->Value < EndOffset) - EndOffset = Entry->Value; - } - DRI.d.b++; - } - } - if (!EndOffset) { - uint64_t Size; - getSectionSize(Sections[SectionIndex-1], Size); - getSectionAddress(Sections[SectionIndex-1], EndOffset); - EndOffset += Size; - } - Result = EndOffset - BeginOffset; - return object_error::success; -} - -error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, - char &Result) const { - const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); +error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI, + char &Result) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); uint8_t Type = Entry->Type; uint16_t Flags = Entry->Flags; @@ -317,9 +188,9 @@ error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const MachOFormat::SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); +error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI, + uint32_t &Result) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); uint8_t MachOType = Entry->Type; uint16_t MachOFlags = Entry->Flags; @@ -347,10 +218,9 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, return object_error::success; } -error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const MachOFormat::SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(Symb); +error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); uint8_t index = Entry->SectionIndex; if (index == 0) @@ -361,10 +231,9 @@ error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const MachOFormat::SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(Symb); +error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); uint8_t n_type = Entry->Type; Res = SymbolRef::ST_Other; @@ -386,97 +255,61 @@ error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, return object_error::success; } -error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFile::begin_symbols() const { +symbol_iterator MachOObjectFileBase::begin_symbols() const { // DRI.d.a = segment number; DRI.d.b = symbol index. DataRefImpl DRI; moveToNextSymbol(DRI); return symbol_iterator(SymbolRef(DRI, this)); } -symbol_iterator MachOObjectFile::end_symbols() const { +symbol_iterator MachOObjectFileBase::end_symbols() const { DataRefImpl DRI; DRI.d.a = getHeader()->NumLoadCommands; return symbol_iterator(SymbolRef(DRI, this)); } -symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { +symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFile::end_dynamic_symbols() const { +symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const { // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); } -library_iterator MachOObjectFile::begin_libraries_needed() const { +library_iterator MachOObjectFileBase::begin_libraries_needed() const { // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -library_iterator MachOObjectFile::end_libraries_needed() const { +library_iterator MachOObjectFileBase::end_libraries_needed() const { // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -StringRef MachOObjectFile::getLoadName() const { +StringRef MachOObjectFileBase::getLoadName() const { // TODO: Implement - report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); + report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase"); } /*===-- Sections ----------------------------------------------------------===*/ -void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Segment) { - const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = - reinterpret_cast*>(Command); - if (DRI.d.b < SegmentLoadCmd->NumSections) - return; - } else if (Command->Type == macho::LCT_Segment64) { - const MachOFormat::SegmentLoadCommand *SegmentLoadCmd = - reinterpret_cast*>(Command); - if (DRI.d.b < SegmentLoadCmd->NumSections) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -error_code MachOObjectFile::getSectionNext(DataRefImpl DRI, - SectionRef &Result) const { - DRI.d.b++; - moveToNextSection(DRI); - Result = SectionRef(DRI, this); - return object_error::success; -} - -const MachOFormat::Section * -MachOObjectFile::getSection(DataRefImpl DRI) const { - assert(!is64Bit()); - const MachOFormat::SectionBase *Addr = getSectionBase(DRI); - return reinterpret_cast*>(Addr); -} - -std::size_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const { +std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { SectionList::const_iterator loc = std::find(Sections.begin(), Sections.end(), Sec); assert(loc != Sections.end() && "Sec is not a valid section!"); return std::distance(Sections.begin(), loc); } -const MachOFormat::SectionBase* -MachOObjectFile::getSectionBase(DataRefImpl DRI) const { - const MachOFormat::LoadCommand *Command = getLoadCommandInfo(DRI.d.a); +const MachOObjectFileBase::SectionBase* +MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { + const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); uintptr_t CommandAddr = reinterpret_cast(Command); bool Is64 = is64Bit(); @@ -487,14 +320,7 @@ MachOObjectFile::getSectionBase(DataRefImpl DRI) const { sizeof(MachOFormat::Section); uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast(SectionAddr); -} - -const MachOFormat::Section * -MachOObjectFile::getSection64(DataRefImpl DRI) const { - assert(is64Bit()); - const MachOFormat::SectionBase *Addr = getSectionBase(DRI); - return reinterpret_cast*>(Addr); + return reinterpret_cast(SectionAddr); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -505,136 +331,61 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl DRI) const { - const MachOFormat::SectionBase *Base = getSectionBase(DRI); +ArrayRef MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const { + const SectionBase *Base = getSectionBase(DRI); return ArrayRef(Base->Name); } -error_code MachOObjectFile::getSectionName(DataRefImpl DRI, - StringRef &Result) const { +error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI, + StringRef &Result) const { ArrayRef Raw = getSectionRawName(DRI); Result = parseSegmentOrSectionName(Raw.data()); return object_error::success; } ArrayRef -MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const MachOFormat::SectionBase *Base = getSectionBase(Sec); +MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); return ArrayRef(Base->SegmentName); } -StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl DRI) const { +StringRef +MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const { ArrayRef Raw = getSectionRawFinalSegmentName(DRI); return parseSegmentOrSectionName(Raw.data()); } -error_code MachOObjectFile::getSectionAddress(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - Result = Sect->Address; - } else { - const MachOFormat::Section *Sect = getSection(DRI); - Result = Sect->Address; - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionSize(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - Result = Sect->Size; - } else { - const MachOFormat::Section *Sect = getSection(DRI); - Result = Sect->Size; - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionContents(DataRefImpl DRI, - StringRef &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - Result = getData(Sect->Offset, Sect->Size); - } else { - const MachOFormat::Section *Sect = getSection(DRI); - Result = getData(Sect->Offset, Sect->Size); - } - return object_error::success; -} - -error_code MachOObjectFile::getSectionAlignment(DataRefImpl DRI, - uint64_t &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - Result = uint64_t(1) << Sect->Align; - } else { - const MachOFormat::Section *Sect = getSection(DRI); - Result = uint64_t(1) << Sect->Align; - } - return object_error::success; -} - -error_code MachOObjectFile::isSectionText(DataRefImpl DRI, - bool &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - Result = Sect->Flags & macho::SF_PureInstructions; - } else { - const MachOFormat::Section *Sect = getSection(DRI); - Result = Sect->Flags & macho::SF_PureInstructions; - } - return object_error::success; -} - -error_code MachOObjectFile::isSectionData(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { +error_code +MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec, + bool &Result) const { // FIXME: Unimplemented. Result = true; return object_error::success; } -error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { +error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec, + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionZeroInit(DataRefImpl DRI, - bool &Result) const { - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(DRI); - unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; - Result = (SectionType == MachO::SectionTypeZeroFill || - SectionType == MachO::SectionTypeZeroFillLarge); - } else { - const MachOFormat::Section *Sect = getSection(DRI); - unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; - Result = (SectionType == MachO::SectionTypeZeroFill || - SectionType == MachO::SectionTypeZeroFillLarge); - } - - return object_error::success; -} - -error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { +error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec, + bool &Result) const { // Consider using the code from isSectionText to look for __const sections. // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS // to use section attributes to distinguish code from data. @@ -644,64 +395,13 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, return object_error::success; } -error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - SymbolRef::Type ST; - getSymbolType(Symb, ST); - if (ST == SymbolRef::ST_Unknown) { - Result = false; - return object_error::success; - } - - uint64_t SectBegin, SectEnd; - getSectionAddress(Sec, SectBegin); - getSectionSize(Sec, SectEnd); - SectEnd += SectBegin; - - if (is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - getSymbol64TableEntry(Symb); - uint64_t SymAddr= Entry->Value; - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); - } else { - const MachOFormat::SymbolTableEntry *Entry = - getSymbolTableEntry(Symb); - uint64_t SymAddr= Entry->Value; - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); - } - - return object_error::success; -} - -relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { +relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl ret; ret.d.b = getSectionIndex(Sec); return relocation_iterator(RelocationRef(ret, this)); } -relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - uint32_t last_reloc; - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(Sec); - last_reloc = Sect->NumRelocationTableEntries; - } else { - const MachOFormat::Section *Sect = getSection(Sec); - last_reloc = Sect->NumRelocationTableEntries; - } - DataRefImpl ret; - ret.d.a = last_reloc; - ret.d.b = getSectionIndex(Sec); - return relocation_iterator(RelocationRef(ret, this)); -} - -section_iterator MachOObjectFile::begin_sections() const { - DataRefImpl DRI; - moveToNextSection(DRI); - return section_iterator(SectionRef(DRI, this)); -} - -section_iterator MachOObjectFile::end_sections() const { +section_iterator MachOObjectFileBase::end_sections() const { DataRefImpl DRI; DRI.d.a = getHeader()->NumLoadCommands; return section_iterator(SectionRef(DRI, this)); @@ -709,208 +409,12 @@ section_iterator MachOObjectFile::end_sections() const { /*===-- Relocations -------------------------------------------------------===*/ -const MachOFormat::RelocationEntry * -MachOObjectFile::getRelocation(DataRefImpl Rel) const { - uint32_t relOffset; - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); - relOffset = Sect->RelocationTableOffset; - } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); - relOffset = Sect->RelocationTableOffset; - } - uint64_t Offset = relOffset + Rel.d.a * sizeof(MachOFormat::RelocationEntry); - StringRef Data = getData(Offset, sizeof(MachOFormat::RelocationEntry)); - return reinterpret_cast(Data.data()); -} - -error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { +error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { ++Rel.d.a; Res = RelocationRef(Rel, this); return object_error::success; } -error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { - const uint8_t* sectAddress = 0; - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); - sectAddress += Sect->Address; - } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); - sectAddress += Sect->Address; - } - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - uint64_t RelAddr = 0; - if (isScattered) - RelAddr = RE->Word0 & 0xFFFFFF; - else - RelAddr = RE->Word0; - - Res = reinterpret_cast(sectAddress + RelAddr); - return object_error::success; -} -error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - if (isScattered) - Res = RE->Word0 & 0xFFFFFF; - else - Res = RE->Word0; - return object_error::success; -} -error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->Word1 & 0xffffff; - bool isExtern = (RE->Word1 >> 27) & 1; - - DataRefImpl Sym; - moveToNextSymbol(Sym); - if (isExtern) { - for (unsigned i = 0; i < SymbolIdx; i++) { - Sym.d.b++; - moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader()->NumLoadCommands && - "Relocation symbol index out of range!"); - } - } - Res = SymbolRef(Sym, this); - return object_error::success; -} -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - Res = RE->Word0; - Res <<= 32; - Res |= RE->Word1; - return object_error::success; -} -error_code MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const { - // TODO: Support scattered relocations. - StringRef res; - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - - unsigned r_type; - if (isScattered) - r_type = (RE->Word0 >> 24) & 0xF; - else - r_type = (RE->Word1 >> 28) & 0xF; - - switch (Arch) { - case Triple::x86: { - static const char *const Table[] = { - "GENERIC_RELOC_VANILLA", - "GENERIC_RELOC_PAIR", - "GENERIC_RELOC_SECTDIFF", - "GENERIC_RELOC_PB_LA_PTR", - "GENERIC_RELOC_LOCAL_SECTDIFF", - "GENERIC_RELOC_TLV" }; - - if (r_type > 6) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::x86_64: { - static const char *const Table[] = { - "X86_64_RELOC_UNSIGNED", - "X86_64_RELOC_SIGNED", - "X86_64_RELOC_BRANCH", - "X86_64_RELOC_GOT_LOAD", - "X86_64_RELOC_GOT", - "X86_64_RELOC_SUBTRACTOR", - "X86_64_RELOC_SIGNED_1", - "X86_64_RELOC_SIGNED_2", - "X86_64_RELOC_SIGNED_4", - "X86_64_RELOC_TLV" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::arm: { - static const char *const Table[] = { - "ARM_RELOC_VANILLA", - "ARM_RELOC_PAIR", - "ARM_RELOC_SECTDIFF", - "ARM_RELOC_LOCAL_SECTDIFF", - "ARM_RELOC_PB_LA_PTR", - "ARM_RELOC_BR24", - "ARM_THUMB_RELOC_BR22", - "ARM_THUMB_32BIT_BRANCH", - "ARM_RELOC_HALF", - "ARM_RELOC_HALF_SECTDIFF" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::ppc: { - static const char *const Table[] = { - "PPC_RELOC_VANILLA", - "PPC_RELOC_PAIR", - "PPC_RELOC_BR14", - "PPC_RELOC_BR24", - "PPC_RELOC_HI16", - "PPC_RELOC_LO16", - "PPC_RELOC_HA16", - "PPC_RELOC_LO14", - "PPC_RELOC_SECTDIFF", - "PPC_RELOC_PB_LA_PTR", - "PPC_RELOC_HI16_SECTDIFF", - "PPC_RELOC_LO16_SECTDIFF", - "PPC_RELOC_HA16_SECTDIFF", - "PPC_RELOC_JBSR", - "PPC_RELOC_LO14_SECTDIFF", - "PPC_RELOC_LOCAL_SECTDIFF" }; - - res = Table[r_type]; - break; - } - case Triple::UnknownArch: - res = "Unknown"; - break; - } - Result.append(res.begin(), res.end()); - return object_error::success; -} -error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - bool isExtern = (RE->Word1 >> 27) & 1; - Res = 0; - if (!isExtern) { - const uint8_t* sectAddress = base(); - if (is64Bit()) { - const MachOFormat::Section *Sect = getSection64(Sections[Rel.d.b]); - sectAddress += Sect->Offset; - } else { - const MachOFormat::Section *Sect = getSection(Sections[Rel.d.b]); - sectAddress += Sect->Offset; - } - Res = reinterpret_cast(sectAddress); - } - return object_error::success; -} // Helper to advance a section or symbol iterator multiple increments at a time. template @@ -928,9 +432,9 @@ void advanceTo(T &it, size_t Val) { report_fatal_error(ec.message()); } -void MachOObjectFile::printRelocationTargetName( - const MachOFormat::RelocationEntry *RE, - raw_string_ostream &fmt) const { +void +MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, + raw_string_ostream &fmt) const { unsigned Arch = getArch(); bool isScattered = (Arch != Triple::x86_64) && (RE->Word0 & macho::RF_Scattered); @@ -998,270 +502,24 @@ void MachOObjectFile::printRelocationTargetName( fmt << S; } -error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - bool isPCRel; - if (isScattered) - isPCRel = ((RE->Word0 >> 30) & 1); - else - isPCRel = ((RE->Word1 >> 24) & 1); - - // Determine any addends that should be displayed with the relocation. - // These require decoding the relocation type, which is triple-specific. - - // X86_64 has entirely custom relocation types. - if (Arch == Triple::x86_64) { - bool isPCRel = ((RE->Word1 >> 24) & 1); - - switch (Type) { - case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD - case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT - printRelocationTargetName(RE, fmt); - fmt << "@GOT"; - if (isPCRel) fmt << "PCREL"; - break; - } - case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86_64_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 0) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - // The X86_64_RELOC_UNSIGNED contains the minuend symbol, - // X86_64_SUBTRACTOR contains to the subtrahend. - printRelocationTargetName(RENext, fmt); - fmt << "-"; - printRelocationTargetName(RE, fmt); - break; - } - case macho::RIT_X86_64_TLV: - printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - printRelocationTargetName(RE, fmt); - fmt << "-1"; - break; - case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - printRelocationTargetName(RE, fmt); - fmt << "-2"; - break; - case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - printRelocationTargetName(RE, fmt); - fmt << "-4"; - break; - default: - printRelocationTargetName(RE, fmt); - break; - } - // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm) { - // Generic relocation types... - switch (Type) { - case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info - return object_error::success; - case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - printRelocationTargetName(RE, fmt); - fmt << "-"; - printRelocationTargetName(RENext, fmt); - break; - } - } - - if (Arch == Triple::x86) { - // All X86 relocations that need special printing were already - // handled in the generic code. - switch (Type) { - case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - printRelocationTargetName(RE, fmt); - fmt << "-"; - printRelocationTargetName(RENext, fmt); - break; - } - case macho::RIT_Generic_TLV: { - printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - } - default: - printRelocationTargetName(RE, fmt); - } - } else { // ARM-specific relocations - switch (Type) { - case macho::RIT_ARM_Half: // ARM_RELOC_HALF - case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF - // Half relocations steal a bit from the length field to encode - // whether this is an upper16 or a lower16 relocation. - bool isUpper; - if (isScattered) - isUpper = (RE->Word0 >> 28) & 1; - else - isUpper = (RE->Word1 >> 25) & 1; - - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - printRelocationTargetName(RE, fmt); - - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const MachOFormat::RelocationEntry *RENext = getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; - else - RType = (RENext->Word1 >> 28) & 0xF; - - if (RType != 1) - report_fatal_error("Expected ARM_RELOC_PAIR after " - "GENERIC_RELOC_HALF"); - - // NOTE: The half of the target virtual address is stashed in the - // address field of the secondary relocation, but we can't reverse - // engineer the constant offset from it without decoding the movw/movt - // instruction to find the other half in its immediate field. - - // ARM_RELOC_HALF_SECTDIFF encodes the second section in the - // symbol/section pointer of the follow-on relocation. - if (Type == macho::RIT_ARM_HalfDifference) { - fmt << "-"; - printRelocationTargetName(RENext, fmt); - } - - fmt << ")"; - break; - } - default: { - printRelocationTargetName(RE, fmt); - } - } - } - } else - printRelocationTargetName(RE, fmt); - - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - return object_error::success; -} - -error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, - bool &Result) const { - const MachOFormat::RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - Result = false; - - // On arches that use the generic relocations, GENERIC_RELOC_PAIR - // is always hidden. - if (Arch == Triple::x86 || Arch == Triple::arm) { - if (Type == macho::RIT_Pair) Result = true; - } else if (Arch == Triple::x86_64) { - // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows - // an X864_64_RELOC_SUBTRACTOR. - if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { - DataRefImpl RelPrev = Rel; - RelPrev.d.a--; - const MachOFormat::RelocationEntry *REPrev = getRelocation(RelPrev); - - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; - - if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; - } - } - - return object_error::success; -} - -error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } -error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData, + StringRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } /*===-- Miscellaneous -----------------------------------------------------===*/ -uint8_t MachOObjectFile::getBytesInAddress() const { +uint8_t MachOObjectFileBase::getBytesInAddress() const { return is64Bit() ? 8 : 4; } -StringRef MachOObjectFile::getFileFormatName() const { +StringRef MachOObjectFileBase::getFileFormatName() const { if (!is64Bit()) { switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: @@ -1292,7 +550,7 @@ StringRef MachOObjectFile::getFileFormatName() const { } } -unsigned MachOObjectFile::getArch() const { +unsigned MachOObjectFileBase::getArch() const { switch (getHeader()->CPUType) { case llvm::MachO::CPUTypeI386: return Triple::x86; diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 7c6565832e..b0a1aca26f 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -52,7 +52,7 @@ static cl::opt static cl::opt DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObjectFile *MachOObj) { +static const Target *GetTarget(const MachOObjectFileBase *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); @@ -108,7 +108,7 @@ struct SymbolSorter { // Print additional information about an address, if available. static void DumpAddress(uint64_t Address, ArrayRef Sections, - const MachOObjectFile *MachOObj, raw_ostream &OS) { + const MachOObjectFileBase *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { uint64_t SectAddr = 0, SectSize = 0; Sections[i].getAddress(SectAddr); @@ -200,7 +200,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, } static void getSectionsAndSymbols(const MachOFormat::Header *Header, - MachOObjectFile *MachOObj, + MachOObjectFileBase *MachOObj, std::vector &Sections, std::vector &Symbols, SmallVectorImpl &FoundFns) { @@ -238,7 +238,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { return; } - OwningPtr MachOOF(static_cast( + OwningPtr MachOOF(static_cast( ObjectFile::createMachOObjectFile(Buff.take()))); const Target *TheTarget = GetTarget(MachOOF.get()); diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 9a36e8253d..4790d7a5fe 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -255,7 +255,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFile *MachO = dyn_cast(Obj)) { + if (const MachOObjectFileBase *MachO = dyn_cast(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); SegmentName = MachO->getSectionFinalSegmentName(DR); } @@ -591,7 +591,7 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFile *MachO = dyn_cast(o)) { + if (const MachOObjectFileBase *MachO = dyn_cast(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); outs() << SegmentName << ","; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 89402808bf..3dad4d6e54 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const llvm::object::MachOObjectFile *Obj, StreamWriter& Writer) + MachODumper(const llvm::object::MachOObjectFileBase *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,7 +43,7 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - const llvm::object::MachOObjectFile *Obj; + const llvm::object::MachOObjectFileBase *Obj; }; } // namespace @@ -54,7 +54,7 @@ namespace llvm { error_code createMachODumper(const object::ObjectFile *Obj, StreamWriter& Writer, OwningPtr &Result) { - const MachOObjectFile *MachOObj = dyn_cast(Obj); + const MachOObjectFileBase *MachOObj = dyn_cast(Obj); if (!MachOObj) return readobj_error::unsupported_obj_file_format; @@ -157,11 +157,11 @@ namespace { }; } -static void getSection(const MachOObjectFile *Obj, +static void getSection(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSection &Section) { - if (Obj->is64Bit()) { - const MachOFormat::Section *Sect = Obj->getSection64(DRI); + if (const MachOObjectFile *O = dyn_cast >(Obj)) { + const MachOObjectFile::Section *Sect = O->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -173,7 +173,8 @@ static void getSection(const MachOObjectFile *Obj, Section.Reserved1 = Sect->Reserved1; Section.Reserved2 = Sect->Reserved2; } else { - const MachOFormat::Section *Sect = Obj->getSection(DRI); + const MachOObjectFile *O2 = cast >(Obj); + const MachOObjectFile::Section *Sect = O2->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -187,20 +188,21 @@ static void getSection(const MachOObjectFile *Obj, } } -static void getSymbol(const MachOObjectFile *Obj, +static void getSymbol(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (Obj->is64Bit()) { - const MachOFormat::SymbolTableEntry *Entry = - Obj->getSymbol64TableEntry(DRI); + if (const MachOObjectFile *O = dyn_cast >(Obj)) { + const MachOObjectFile::SymbolTableEntry *Entry = + O->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; Symbol.Flags = Entry->Flags; Symbol.Value = Entry->Value; } else { - const MachOFormat::SymbolTableEntry *Entry = - Obj->getSymbolTableEntry(DRI); + const MachOObjectFile *O2 = cast >(Obj); + const MachOObjectFile::SymbolTableEntry *Entry = + O2->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; Symbol.SectionIndex = Entry->SectionIndex; diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index 29d91a0e92..ffe8712a65 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -233,7 +233,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { // On Darwin we may find DWARF in separate object file in // resource directory. ObjectFile *DbgObj = Obj; - if (isa(Obj)) { + if (isa(Obj)) { const std::string &ResourceName = getDarwinDWARFResourceForModule(ModuleName); ObjectFile *ResourceObj = getObjectFile(ResourceName); -- cgit v1.2.3-70-g09d2 From a2561a0153237291980722383f409a6499b12efc Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 10 Apr 2013 03:48:25 +0000 Subject: Template the MachO types over endianness. For now they are still only used as little endian. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179147 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 239 +++++++++++++++++++++++---------------- lib/Object/MachOObjectFile.cpp | 12 +- tools/llvm-objdump/MachODump.cpp | 11 +- 3 files changed, 153 insertions(+), 109 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 3b0ca6c3ce..1b0ca29543 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -27,152 +27,193 @@ namespace llvm { namespace object { +using support::endianness; + +template +struct MachOType { + static const endianness TargetEndianness = E; + static const bool Is64Bits = B; +}; + +template +struct MachODataTypeTypedefHelperCommon { + typedef support::detail::packed_endian_specific_integral + MachOInt16; + typedef support::detail::packed_endian_specific_integral + MachOInt32; + typedef support::detail::packed_endian_specific_integral + MachOInt64; +}; + +#define LLVM_MACHOB_IMPORT_TYPES(E) \ +typedef typename MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \ +typedef typename MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \ +typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; + +template +struct MachODataTypeTypedefHelper; + +template class MachOT, endianness TargetEndianness> +struct MachODataTypeTypedefHelper > { + typedef MachODataTypeTypedefHelperCommon Base; + typedef typename Base::MachOInt32 MachOIntPtr; +}; + +template class MachOT, endianness TargetEndianness> +struct MachODataTypeTypedefHelper > { + typedef MachODataTypeTypedefHelperCommon Base; + typedef typename Base::MachOInt64 MachOIntPtr; +}; + +#define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \ +LLVM_MACHOB_IMPORT_TYPES(E) \ +typedef typename \ + MachODataTypeTypedefHelper >::MachOIntPtr MachOIntPtr; + namespace MachOFormat { struct SectionBase { char Name[16]; char SegmentName[16]; }; - template + template struct Section; - template<> - struct Section { + template class MachOT, endianness TargetEndianness> + struct Section > { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) char Name[16]; char SegmentName[16]; - support::ulittle32_t Address; - support::ulittle32_t Size; - support::ulittle32_t Offset; - support::ulittle32_t Align; - support::ulittle32_t RelocationTableOffset; - support::ulittle32_t NumRelocationTableEntries; - support::ulittle32_t Flags; - support::ulittle32_t Reserved1; - support::ulittle32_t Reserved2; + MachOInt32 Address; + MachOInt32 Size; + MachOInt32 Offset; + MachOInt32 Align; + MachOInt32 RelocationTableOffset; + MachOInt32 NumRelocationTableEntries; + MachOInt32 Flags; + MachOInt32 Reserved1; + MachOInt32 Reserved2; }; - template<> - struct Section { + template class MachOT, + endianness TargetEndianness> + struct Section > { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) char Name[16]; char SegmentName[16]; - support::ulittle64_t Address; - support::ulittle64_t Size; - support::ulittle32_t Offset; - support::ulittle32_t Align; - support::ulittle32_t RelocationTableOffset; - support::ulittle32_t NumRelocationTableEntries; - support::ulittle32_t Flags; - support::ulittle32_t Reserved1; - support::ulittle32_t Reserved2; - support::ulittle32_t Reserved3; + MachOInt64 Address; + MachOInt64 Size; + MachOInt32 Offset; + MachOInt32 Align; + MachOInt32 RelocationTableOffset; + MachOInt32 NumRelocationTableEntries; + MachOInt32 Flags; + MachOInt32 Reserved1; + MachOInt32 Reserved2; + MachOInt32 Reserved3; }; + template struct RelocationEntry { - support::ulittle32_t Word0; - support::ulittle32_t Word1; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 Word0; + MachOInt32 Word1; }; + template struct SymbolTableEntryBase { - support::ulittle32_t StringIndex; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 StringIndex; uint8_t Type; uint8_t SectionIndex; - support::ulittle16_t Flags; + MachOInt16 Flags; }; - template + template struct SymbolTableEntry; - template<> - struct SymbolTableEntry { - support::ulittle32_t StringIndex; - uint8_t Type; - uint8_t SectionIndex; - support::ulittle16_t Flags; - support::ulittle32_t Value; - }; - - template<> - struct SymbolTableEntry { - support::ulittle32_t StringIndex; + template class MachOT, endianness TargetEndianness, + bool Is64Bits> + struct SymbolTableEntry > { + LLVM_MACHO_IMPORT_TYPES(MachOT, TargetEndianness, Is64Bits) + MachOInt32 StringIndex; uint8_t Type; uint8_t SectionIndex; - support::ulittle16_t Flags; - support::ulittle64_t Value; + MachOInt16 Flags; + MachOIntPtr Value; }; + template struct LoadCommand { - support::ulittle32_t Type; - support::ulittle32_t Size; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 Type; + MachOInt32 Size; }; + template struct SymtabLoadCommand { - support::ulittle32_t Type; - support::ulittle32_t Size; - support::ulittle32_t SymbolTableOffset; - support::ulittle32_t NumSymbolTableEntries; - support::ulittle32_t StringTableOffset; - support::ulittle32_t StringTableSize; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 Type; + MachOInt32 Size; + MachOInt32 SymbolTableOffset; + MachOInt32 NumSymbolTableEntries; + MachOInt32 StringTableOffset; + MachOInt32 StringTableSize; }; - template + template struct SegmentLoadCommand; - template<> - struct SegmentLoadCommand { - support::ulittle32_t Type; - support::ulittle32_t Size; + template class MachOT, endianness TargetEndianness, + bool Is64Bits> + struct SegmentLoadCommand > { + LLVM_MACHO_IMPORT_TYPES(MachOT, TargetEndianness, Is64Bits) + MachOInt32 Type; + MachOInt32 Size; char Name[16]; - support::ulittle32_t VMAddress; - support::ulittle32_t VMSize; - support::ulittle32_t FileOffset; - support::ulittle32_t FileSize; - support::ulittle32_t MaxVMProtection; - support::ulittle32_t InitialVMProtection; - support::ulittle32_t NumSections; - support::ulittle32_t Flags; - }; - - template<> - struct SegmentLoadCommand { - support::ulittle32_t Type; - support::ulittle32_t Size; - char Name[16]; - support::ulittle64_t VMAddress; - support::ulittle64_t VMSize; - support::ulittle64_t FileOffset; - support::ulittle64_t FileSize; - support::ulittle32_t MaxVMProtection; - support::ulittle32_t InitialVMProtection; - support::ulittle32_t NumSections; - support::ulittle32_t Flags; + MachOIntPtr VMAddress; + MachOIntPtr VMSize; + MachOIntPtr FileOffset; + MachOIntPtr FileSize; + MachOInt32 MaxVMProtection; + MachOInt32 InitialVMProtection; + MachOInt32 NumSections; + MachOInt32 Flags; }; + template struct LinkeditDataLoadCommand { - support::ulittle32_t Type; - support::ulittle32_t Size; - support::ulittle32_t DataOffset; - support::ulittle32_t DataSize; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 Type; + MachOInt32 Size; + MachOInt32 DataOffset; + MachOInt32 DataSize; }; + template struct Header { - support::ulittle32_t Magic; - support::ulittle32_t CPUType; - support::ulittle32_t CPUSubtype; - support::ulittle32_t FileType; - support::ulittle32_t NumLoadCommands; - support::ulittle32_t SizeOfLoadCommands; - support::ulittle32_t Flags; + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt32 Magic; + MachOInt32 CPUType; + MachOInt32 CPUSubtype; + MachOInt32 FileType; + MachOInt32 NumLoadCommands; + MachOInt32 SizeOfLoadCommands; + MachOInt32 Flags; }; } class MachOObjectFileBase : public ObjectFile { public: - typedef MachOFormat::SymbolTableEntryBase SymbolTableEntryBase; - typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; - typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::SymbolTableEntryBase + SymbolTableEntryBase; + typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; + typedef MachOFormat::RelocationEntry RelocationEntry; typedef MachOFormat::SectionBase SectionBase; - typedef MachOFormat::LoadCommand LoadCommand; - typedef MachOFormat::Header Header; + typedef MachOFormat::LoadCommand LoadCommand; + typedef MachOFormat::Header Header; + typedef MachOFormat::LinkeditDataLoadCommand + LinkeditDataLoadCommand; MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); @@ -253,9 +294,11 @@ private: template struct MachOObjectFileHelperCommon { - typedef MachOFormat::SegmentLoadCommand SegmentLoadCommand; - typedef MachOFormat::SymbolTableEntry SymbolTableEntry; - typedef MachOFormat::Section Section; + typedef MachOFormat::SegmentLoadCommand > + SegmentLoadCommand; + typedef MachOFormat::SymbolTableEntry > + SymbolTableEntry; + typedef MachOFormat::Section > Section; }; template diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 20b66d94e8..33c63b0f89 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -127,8 +127,8 @@ MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, unsigned Index = DRI.d.b; unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOFormat::SymbolTableEntry) : - sizeof(MachOFormat::SymbolTableEntry); + sizeof(MachOObjectFile::SymbolTableEntry) : + sizeof(MachOObjectFile::SymbolTableEntry); uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; StringRef Data = getData(Offset, SymbolTableEntrySize); @@ -314,10 +314,10 @@ MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { bool Is64 = is64Bit(); unsigned SegmentLoadSize = - Is64 ? sizeof(MachOFormat::SegmentLoadCommand) : - sizeof(MachOFormat::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOFormat::Section) : - sizeof(MachOFormat::Section); + Is64 ? sizeof(MachOObjectFile::SegmentLoadCommand) : + sizeof(MachOObjectFile::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(MachOObjectFile::Section) : + sizeof(MachOObjectFile::Section); uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; return reinterpret_cast(SectionAddr); diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index b0a1aca26f..d1e7d695f6 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -199,7 +199,7 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -static void getSectionsAndSymbols(const MachOFormat::Header *Header, +static void getSectionsAndSymbols(const MachOObjectFileBase::Header *Header, MachOObjectFileBase *MachOObj, std::vector &Sections, std::vector &Symbols, @@ -218,12 +218,13 @@ static void getSectionsAndSymbols(const MachOFormat::Header *Header, } for (unsigned i = 0; i != Header->NumLoadCommands; ++i) { - const MachOFormat::LoadCommand *Command = MachOObj->getLoadCommandInfo(i); + const MachOObjectFileBase::LoadCommand *Command = + MachOObj->getLoadCommandInfo(i); if (Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - const MachOFormat::LinkeditDataLoadCommand *LLC = - reinterpret_cast(Command); + const MachOObjectFileBase::LinkeditDataLoadCommand *LLC = + reinterpret_cast(Command); MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); } @@ -269,7 +270,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const MachOFormat::Header *Header = MachOOF->getHeader(); + const MachOObjectFileBase::Header *Header = MachOOF->getHeader(); std::vector Sections; std::vector Symbols; -- cgit v1.2.3-70-g09d2 From b08c6df6787971502bd51e30b0f1038c1ea0dc2c Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 10 Apr 2013 15:33:44 +0000 Subject: Template MachOObjectFile over endianness too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179179 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 189 ++++++++++++++++++++----------------- lib/Object/MachOObjectFile.cpp | 18 ++-- tools/llvm-readobj/MachODumper.cpp | 16 ++-- 3 files changed, 117 insertions(+), 106 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index f08b3b5257..49800fc381 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -289,34 +289,41 @@ private: const SymtabLoadCommand *SymtabLoadCmd) const; }; -template -struct MachOObjectFileHelperCommon { - typedef MachOFormat::SegmentLoadCommand > +template +struct MachOObjectFileHelperCommon; + +template +struct MachOObjectFileHelperCommon > { + typedef + MachOFormat::SegmentLoadCommand > SegmentLoadCommand; - typedef MachOFormat::SymbolTableEntry > + typedef MachOFormat::SymbolTableEntry > SymbolTableEntry; - typedef MachOFormat::Section > Section; + typedef MachOFormat::Section > Section; }; -template +template struct MachOObjectFileHelper; -template<> -struct MachOObjectFileHelper : - public MachOObjectFileHelperCommon { +template +struct MachOObjectFileHelper > : + public MachOObjectFileHelperCommon > { static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; }; -template<> -struct MachOObjectFileHelper : - public MachOObjectFileHelperCommon { +template +struct MachOObjectFileHelper > : + public MachOObjectFileHelperCommon > { static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; }; -template +template class MachOObjectFile : public MachOObjectFileBase { public: - typedef MachOObjectFileHelper Helper; + static const endianness TargetEndianness = MachOT::TargetEndianness; + static const bool Is64Bits = MachOT::Is64Bits; + + typedef MachOObjectFileHelper Helper; static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; typedef typename Helper::SymbolTableEntry SymbolTableEntry; @@ -357,10 +364,10 @@ public: void moveToNextSection(DataRefImpl &DRI) const; }; -template -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, - error_code &ec) : - MachOObjectFileBase(Object, is64Bits, ec) { +template +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, + error_code &ec) : + MachOObjectFileBase(Object, Is64Bits, ec) { DataRefImpl DRI; moveToNextSection(DRI); uint32_t LoadCommandCount = getHeader()->NumLoadCommands; @@ -371,28 +378,28 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, } } -template -bool MachOObjectFile::classof(const Binary *v) { - return v->getType() == getMachOType(true, is64Bits); +template +bool MachOObjectFile::classof(const Binary *v) { + return v->getType() == getMachOType(true, Is64Bits); } -template -const typename MachOObjectFile::Section * -MachOObjectFile::getSection(DataRefImpl DRI) const { +template +const typename MachOObjectFile::Section * +MachOObjectFile::getSection(DataRefImpl DRI) const { const SectionBase *Addr = getSectionBase(DRI); return reinterpret_cast(Addr); } -template -const typename MachOObjectFile::SymbolTableEntry * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { +template +const typename MachOObjectFile::SymbolTableEntry * +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); return reinterpret_cast(Base); } -template -const typename MachOObjectFile::RelocationEntry * -MachOObjectFile::getRelocation(DataRefImpl Rel) const { +template +const typename MachOObjectFile::RelocationEntry * +MachOObjectFile::getRelocation(DataRefImpl Rel) const { const Section *Sect = getSection(Sections[Rel.d.b]); uint32_t RelOffset = Sect->RelocationTableOffset; uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); @@ -400,53 +407,53 @@ MachOObjectFile::getRelocation(DataRefImpl Rel) const { return reinterpret_cast(Data.data()); } -template +template error_code -MachOObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const { const Section *Sect = getSection(Sec); Res = Sect->Address; return object_error::success; } -template +template error_code -MachOObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Res) const { const Section *Sect = getSection(Sec); Res = Sect->Size; return object_error::success; } -template +template error_code -MachOObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Res) const { +MachOObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { const Section *Sect = getSection(Sec); Res = getData(Sect->Offset, Sect->Size); return object_error::success; } -template +template error_code -MachOObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { const Section *Sect = getSection(Sec); Res = uint64_t(1) << Sect->Align; return object_error::success; } -template +template error_code -MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { +MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { const Section *Sect = getSection(Sec); Res = Sect->Flags & macho::SF_PureInstructions; return object_error::success; } -template +template error_code -MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { +MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { const Section *Sect = getSection(Sec); unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; Res = SectionType == MachO::SectionTypeZeroFill || @@ -454,9 +461,9 @@ MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { return object_error::success; } -template +template relocation_iterator -MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { +MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { const Section *Sect = getSection(Sec); uint32_t LastReloc = Sect->NumRelocationTableEntries; DataRefImpl Ret; @@ -465,10 +472,10 @@ MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { return relocation_iterator(RelocationRef(Ret, this)); } -template +template error_code -MachOObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { +MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { const Section *Sect = getSection(Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); @@ -486,10 +493,10 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { +MachOObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); @@ -502,10 +509,10 @@ MachOObjectFile::getRelocationOffset(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const { +MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { const RelocationEntry *RE = getRelocation(Rel); uint32_t SymbolIdx = RE->Word1 & 0xffffff; bool isExtern = (RE->Word1 >> 27) & 1; @@ -524,10 +531,10 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const { +MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); bool isExtern = (RE->Word1 >> 27) & 1; Res = 0; @@ -540,9 +547,9 @@ MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, return object_error::success; } -template -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { +template +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); Res = RE->Word0; Res <<= 32; @@ -550,9 +557,9 @@ error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, +MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const { // TODO: Support scattered relocations. StringRef res; @@ -652,9 +659,9 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationValueString(DataRefImpl Rel, +MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { const RelocationEntry *RE = getRelocation(Rel); @@ -864,10 +871,10 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getRelocationHidden(DataRefImpl Rel, - bool &Result) const { +MachOObjectFile::getRelocationHidden(DataRefImpl Rel, + bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); @@ -902,10 +909,10 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, return object_error::success; } -template +template error_code -MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Res) const { +MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Res) const { const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); Res = Entry->Value; if (Entry->SectionIndex) { @@ -916,11 +923,11 @@ MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, return object_error::success; } -template +template error_code -MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { SymbolRef::Type ST; getSymbolType(Symb, ST); if (ST == SymbolRef::ST_Unknown) { @@ -940,16 +947,16 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, return object_error::success; } -template -error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const { +template +error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const { const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); Res = Entry->Value; return object_error::success; } -template -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, +template +error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { uint32_t LoadCommandCount = getHeader()->NumLoadCommands; uint64_t BeginOffset; @@ -992,24 +999,24 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, return object_error::success; } -template -error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, - SectionRef &Res) const { +template +error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Res) const { Sec.d.b++; moveToNextSection(Sec); Res = SectionRef(Sec, this); return object_error::success; } -template -section_iterator MachOObjectFile::begin_sections() const { +template +section_iterator MachOObjectFile::begin_sections() const { DataRefImpl DRI; moveToNextSection(DRI); return section_iterator(SectionRef(DRI, this)); } -template -void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { +template +void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { uint32_t LoadCommandCount = getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); @@ -1025,6 +1032,10 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { } } + typedef MachOObjectFile > + MachOObjectFile32Le; + typedef MachOObjectFile > + MachOObjectFile64Le; } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 33c63b0f89..f4df8e012c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -35,7 +35,7 @@ MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, } bool MachOObjectFileBase::is64Bit() const { - return isa >(this); + return isa(this); } const MachOObjectFileBase::LoadCommand * @@ -86,9 +86,9 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; ObjectFile *Ret; if (Is64Bits) - Ret = new MachOObjectFile(Buffer, ec); + Ret = new MachOObjectFile64Le(Buffer, ec); else - Ret = new MachOObjectFile(Buffer, ec); + Ret = new MachOObjectFile32Le(Buffer, ec); if (ec) return NULL; return Ret; @@ -127,8 +127,8 @@ MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, unsigned Index = DRI.d.b; unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFile::SymbolTableEntry) : - sizeof(MachOObjectFile::SymbolTableEntry); + sizeof(MachOObjectFile64Le::SymbolTableEntry) : + sizeof(MachOObjectFile32Le::SymbolTableEntry); uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; StringRef Data = getData(Offset, SymbolTableEntrySize); @@ -314,10 +314,10 @@ MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { bool Is64 = is64Bit(); unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFile::SegmentLoadCommand) : - sizeof(MachOObjectFile::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFile::Section) : - sizeof(MachOObjectFile::Section); + Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) : + sizeof(MachOObjectFile32Le::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) : + sizeof(MachOObjectFile32Le::Section); uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; return reinterpret_cast(SectionAddr); diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 3dad4d6e54..2073ddf463 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -160,8 +160,8 @@ namespace { static void getSection(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSection &Section) { - if (const MachOObjectFile *O = dyn_cast >(Obj)) { - const MachOObjectFile::Section *Sect = O->getSection(DRI); + if (const MachOObjectFile64Le *O = dyn_cast(Obj)) { + const MachOObjectFile64Le::Section *Sect = O->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -173,8 +173,8 @@ static void getSection(const MachOObjectFileBase *Obj, Section.Reserved1 = Sect->Reserved1; Section.Reserved2 = Sect->Reserved2; } else { - const MachOObjectFile *O2 = cast >(Obj); - const MachOObjectFile::Section *Sect = O2->getSection(DRI); + const MachOObjectFile32Le *O2 = cast(Obj); + const MachOObjectFile32Le::Section *Sect = O2->getSection(DRI); Section.Address = Sect->Address; Section.Size = Sect->Size; @@ -191,8 +191,8 @@ static void getSection(const MachOObjectFileBase *Obj, static void getSymbol(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (const MachOObjectFile *O = dyn_cast >(Obj)) { - const MachOObjectFile::SymbolTableEntry *Entry = + if (const MachOObjectFile64Le *O = dyn_cast(Obj)) { + const MachOObjectFile64Le::SymbolTableEntry *Entry = O->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; @@ -200,8 +200,8 @@ static void getSymbol(const MachOObjectFileBase *Obj, Symbol.Flags = Entry->Flags; Symbol.Value = Entry->Value; } else { - const MachOObjectFile *O2 = cast >(Obj); - const MachOObjectFile::SymbolTableEntry *Entry = + const MachOObjectFile32Le *O2 = cast(Obj); + const MachOObjectFile32Le::SymbolTableEntry *Entry = O2->getSymbolTableEntry(DRI); Symbol.StringIndex = Entry->StringIndex; Symbol.Type = Entry->Type; -- cgit v1.2.3-70-g09d2 From 8bf80061ba44af16b4597627ca7d6d7fc1bed64e Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 11 Apr 2013 02:21:31 +0000 Subject: Fix MachO's getRelocationAdditionalInfo. It was returning the loaded address of the section containing the relocation, which really doesn't seem to be the intent of this function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179255 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 20 ++------------------ lib/Object/MachOObjectFile.cpp | 6 ++++++ 2 files changed, 8 insertions(+), 18 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 49800fc381..b02e1ac100 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -271,6 +271,8 @@ protected: virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; std::size_t getSectionIndex(DataRefImpl Sec) const; @@ -346,8 +348,6 @@ public: virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; @@ -531,22 +531,6 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, return object_error::success; } -template -error_code -MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const { - const RelocationEntry *RE = getRelocation(Rel); - bool isExtern = (RE->Word1 >> 27) & 1; - Res = 0; - if (!isExtern) { - const uint8_t* sectAddress = base(); - const Section *Sect = getSection(Sections[Rel.d.b]); - sectAddress += Sect->Offset; - Res = reinterpret_cast(sectAddress); - } - return object_error::success; -} - template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index f4df8e012c..c846206e6e 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -512,6 +512,12 @@ error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData, report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); } +error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { + Res = 0; + return object_error::success; +} + /*===-- Miscellaneous -----------------------------------------------------===*/ -- cgit v1.2.3-70-g09d2 From 4edf092787cab37d46da96eb1e9df0677ca30b1d Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 11 Apr 2013 16:31:37 +0000 Subject: Print more information about relocations. With this patch llvm-readobj now prints if a relocation is pcrel, its length, if it is extern and if it is scattered. It also refactors the code a bit to use bit fields instead of shifts and masks all over the place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179294 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 118 ++++++++++++++---------------- lib/Object/MachOObjectFile.cpp | 52 +++++++++++-- test/tools/llvm-readobj/relocations.test | 14 ++-- test/tools/llvm-readobj/sections-ext.test | 14 ++-- tools/llvm-readobj/MachODumper.cpp | 16 +++- 5 files changed, 124 insertions(+), 90 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index b02e1ac100..1fd8b6c92c 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -115,8 +115,23 @@ namespace MachOFormat { template struct RelocationEntry { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - MachOInt32 Word0; - MachOInt32 Word1; + MachOInt32 Address; + unsigned SymbolNum : 24; + unsigned PCRel : 1; + unsigned Length : 2; + unsigned External : 1; + unsigned Type : 4; + }; + + template + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + unsigned Address : 24; + unsigned Type : 4; + unsigned Length : 2; + unsigned PCRel : 1; + unsigned Scattered : 1; + MachOInt32 Value; }; template @@ -206,6 +221,8 @@ public: SymbolTableEntryBase; typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry + ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; typedef MachOFormat::LoadCommand LoadCommand; typedef MachOFormat::Header Header; @@ -243,6 +260,11 @@ public: const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + bool isScattered(const RelocationEntry *RE) const; + bool isPCRel(const RelocationEntry *RE) const; + unsigned getLength(const RelocationEntry *RE) const; + unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); @@ -479,15 +501,12 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, const Section *Sect = getSection(Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); uint64_t RelAddr; - if (isScattered) - RelAddr = RE->Word0 & 0xFFFFFF; + if (isScattered(RE)) + RelAddr = RE->Address & 0xFFFFFF; else - RelAddr = RE->Word0; + RelAddr = RE->Address; Res = SectAddress + RelAddr; return object_error::success; @@ -498,14 +517,10 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - if (isScattered) - Res = RE->Word0 & 0xFFFFFF; + if (isScattered(RE)) + Res = RE->Address & 0xFFFFFF; else - Res = RE->Word0; + Res = RE->Address; return object_error::success; } @@ -514,8 +529,8 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { const RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->Word1 & 0xffffff; - bool isExtern = (RE->Word1 >> 27) & 1; + uint32_t SymbolIdx = RE->SymbolNum; + bool isExtern = RE->External; DataRefImpl Sym; moveToNextSymbol(Sym); @@ -535,9 +550,7 @@ template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = RE->Word0; - Res <<= 32; - Res |= RE->Word1; + Res = getType(RE); return object_error::success; } @@ -550,14 +563,8 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned r_type; - if (isScattered) - r_type = (RE->Word0 >> 24) & 0xF; - else - r_type = (RE->Word1 >> 28) & 0xF; + unsigned r_type = getType(RE); switch (Arch) { case Triple::x86: { @@ -650,30 +657,20 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); + bool IsScattered = isScattered(RE); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - bool isPCRel; - if (isScattered) - isPCRel = ((RE->Word0 >> 30) & 1); - else - isPCRel = ((RE->Word1 >> 24) & 1); + unsigned Type = getType(RE); + bool IsPCRel = isPCRel(RE); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. // X86_64 has entirely custom relocation types. if (Arch == Triple::x86_64) { - bool isPCRel = ((RE->Word1 >> 24) & 1); + bool isPCRel = RE->PCRel; switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD @@ -691,7 +688,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86_64_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = (RENext->Word1 >> 28) & 0xF; + unsigned RType = RENext->Type; if (RType != 0) report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " "X86_64_RELOC_SUBTRACTOR."); @@ -738,12 +735,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->Type; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); @@ -767,12 +764,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->Type; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); @@ -785,7 +782,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, case macho::RIT_Generic_TLV: { printRelocationTargetName(RE, fmt); fmt << "@TLV"; - if (isPCRel) fmt << "P"; + if (IsPCRel) fmt << "P"; break; } default: @@ -798,10 +795,10 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // Half relocations steal a bit from the length field to encode // whether this is an upper16 or a lower16 relocation. bool isUpper; - if (isScattered) - isUpper = (RE->Word0 >> 28) & 1; + if (IsScattered) + isUpper = (RE->Address >> 28) & 1; else - isUpper = (RE->Word1 >> 25) & 1; + isUpper = (RE->Length >> 1) & 1; if (isUpper) fmt << ":upper16:("; @@ -816,12 +813,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // ARM half relocs must be followed by a relocation of type // ARM_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->Type; if (RType != 1) report_fatal_error("Expected ARM_RELOC_PAIR after " @@ -860,15 +857,8 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; + unsigned Type = getType(RE); Result = false; @@ -884,7 +874,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, RelPrev.d.a--; const RelocationEntry *REPrev = getRelocation(RelPrev); - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + unsigned PrevType = REPrev->Type; if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c846206e6e..98e28db88d 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -80,6 +80,46 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } +const MachOObjectFileBase::RelocationEntry * +MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { + if (const MachOObjectFile32Le *O = dyn_cast(this)) + return O->getRelocation(Rel); + const MachOObjectFile64Le *O = dyn_cast(this); + return O->getRelocation(Rel); +} + +bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { + unsigned Arch = getArch(); + return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); +} + +bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->PCRel; + } + return RE->PCRel; +} + +unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->Length; + } + return RE->Length; +} + +unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->Type; + } + return RE->Type; +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; @@ -435,16 +475,12 @@ void advanceTo(T &it, size_t Val) { void MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, raw_string_ostream &fmt) const { - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - // Target of a scattered relocation is an address. In the interest of // generating pretty output, scan through the symbol table looking for a // symbol that aligns with that address. If we find one, print it. // Otherwise, we just print the hex address of the target. - if (isScattered) { - uint32_t Val = RE->Word1; + if (isScattered(RE)) { + uint32_t Val = RE->SymbolNum; error_code ec; for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; @@ -486,8 +522,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, } StringRef S; - bool isExtern = (RE->Word1 >> 27) & 1; - uint32_t Val = RE->Word1 & 0xFFFFFF; + bool isExtern = RE->External; + uint32_t Val = RE->Address; if (isExtern) { symbol_iterator SI = begin_symbols(); diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index b4b876a70b..96aac231db 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -26,17 +26,17 @@ ELF-NEXT: ] MACHO-I386: Relocations [ MACHO-I386-NEXT: Section __text { -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: } MACHO-I386-NEXT: ] MACHO-X86-64: Relocations [ MACHO-X86-64-NEXT: Section __text { -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a16bca2b19..a12d9e4646 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -153,10 +153,10 @@ MACHO-I386-NEXT: ] MACHO-I386-NEXT: Reserved1: 0x0 MACHO-I386-NEXT: Reserved2: 0x0 MACHO-I386-NEXT: Relocations [ -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: ] MACHO-I386-NEXT: Symbols [ MACHO-I386-NEXT: Symbol { @@ -196,9 +196,9 @@ MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: Relocations [ -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Symbols [ MACHO-X86-64-NEXT: Symbol { diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 2073ddf463..b027d40bea 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -330,20 +330,28 @@ void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; - int64_t Info; StringRef SymbolName; SymbolRef Symbol; if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; - if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; if (error(Symbol.getName(SymbolName))) return; + DataRefImpl DR = RelI->getRawDataRefImpl(); + const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); + bool IsScattered = Obj->isScattered(RE); + raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << RelocName + << " " << Obj->isPCRel(RE) + << " " << Obj->getLength(RE); + if (IsScattered) + OS << " n/a"; + else + OS << " " << RE->External; + OS << " " << RelocName + << " " << IsScattered << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) << "\n"; } -- cgit v1.2.3-70-g09d2 From 59a8b5a8f09ae4c4f3b0e3d8025c6b4cf3ca1f1a Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 11 Apr 2013 17:46:10 +0000 Subject: Revert my last two commits while I debug what is wrong in a big endian host. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179303 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 125 +++++++++++++++--------------- lib/Object/MachOObjectFile.cpp | 52 ++----------- test/tools/llvm-readobj/relocations.test | 14 ++-- test/tools/llvm-readobj/sections-ext.test | 14 ++-- tools/llvm-readobj/MachODumper.cpp | 16 +--- 5 files changed, 90 insertions(+), 131 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 7bdb638b26..b02e1ac100 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -112,33 +112,11 @@ namespace MachOFormat { MachOInt32 Reserved3; }; - struct MachOInt24 { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; - } - }; - template struct RelocationEntry { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned External : 1; - unsigned Type : 4; - }; - - template - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - unsigned Address : 24; - unsigned Type : 4; - unsigned Length : 2; - unsigned PCRel : 1; - unsigned Scattered : 1; - MachOInt32 Value; + MachOInt32 Word0; + MachOInt32 Word1; }; template @@ -228,8 +206,6 @@ public: SymbolTableEntryBase; typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; typedef MachOFormat::RelocationEntry RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry - ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; typedef MachOFormat::LoadCommand LoadCommand; typedef MachOFormat::Header Header; @@ -267,11 +243,6 @@ public: const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isScattered(const RelocationEntry *RE) const; - bool isPCRel(const RelocationEntry *RE) const; - unsigned getLength(const RelocationEntry *RE) const; - unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); @@ -508,12 +479,15 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, const Section *Sect = getSection(Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); uint64_t RelAddr; - if (isScattered(RE)) - RelAddr = RE->Address & 0xFFFFFF; + if (isScattered) + RelAddr = RE->Word0 & 0xFFFFFF; else - RelAddr = RE->Address; + RelAddr = RE->Word0; Res = SectAddress + RelAddr; return object_error::success; @@ -524,10 +498,14 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - if (isScattered(RE)) - Res = RE->Address & 0xFFFFFF; + + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + if (isScattered) + Res = RE->Word0 & 0xFFFFFF; else - Res = RE->Address; + Res = RE->Word0; return object_error::success; } @@ -536,8 +514,8 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { const RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->SymbolNum; - bool isExtern = RE->External; + uint32_t SymbolIdx = RE->Word1 & 0xffffff; + bool isExtern = (RE->Word1 >> 27) & 1; DataRefImpl Sym; moveToNextSymbol(Sym); @@ -557,7 +535,9 @@ template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = getType(RE); + Res = RE->Word0; + Res <<= 32; + Res |= RE->Word1; return object_error::success; } @@ -570,8 +550,14 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); - unsigned r_type = getType(RE); + unsigned r_type; + if (isScattered) + r_type = (RE->Word0 >> 24) & 0xF; + else + r_type = (RE->Word1 >> 28) & 0xF; switch (Arch) { case Triple::x86: { @@ -664,20 +650,30 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool IsScattered = isScattered(RE); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type = getType(RE); - bool IsPCRel = isPCRel(RE); + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; + + bool isPCRel; + if (isScattered) + isPCRel = ((RE->Word0 >> 30) & 1); + else + isPCRel = ((RE->Word1 >> 24) & 1); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. // X86_64 has entirely custom relocation types. if (Arch == Triple::x86_64) { - bool isPCRel = RE->PCRel; + bool isPCRel = ((RE->Word1 >> 24) & 1); switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD @@ -695,7 +691,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86_64_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = RENext->Type; + unsigned RType = (RENext->Word1 >> 28) & 0xF; if (RType != 0) report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " "X86_64_RELOC_SUBTRACTOR."); @@ -742,12 +738,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); + (RENext->Word0 & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; + RType = (RENext->Word0 >> 24) & 0xF; else - RType = RENext->Type; + RType = (RENext->Word1 >> 28) & 0xF; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); @@ -771,12 +767,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); + (RENext->Word0 & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; + RType = (RENext->Word0 >> 24) & 0xF; else - RType = RENext->Type; + RType = (RENext->Word1 >> 28) & 0xF; if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); @@ -789,7 +785,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, case macho::RIT_Generic_TLV: { printRelocationTargetName(RE, fmt); fmt << "@TLV"; - if (IsPCRel) fmt << "P"; + if (isPCRel) fmt << "P"; break; } default: @@ -802,10 +798,10 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // Half relocations steal a bit from the length field to encode // whether this is an upper16 or a lower16 relocation. bool isUpper; - if (IsScattered) - isUpper = (RE->Address >> 28) & 1; + if (isScattered) + isUpper = (RE->Word0 >> 28) & 1; else - isUpper = (RE->Length >> 1) & 1; + isUpper = (RE->Word1 >> 25) & 1; if (isUpper) fmt << ":upper16:("; @@ -820,12 +816,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // ARM half relocs must be followed by a relocation of type // ARM_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); + (RENext->Word0 & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; + RType = (RENext->Word0 >> 24) & 0xF; else - RType = RENext->Type; + RType = (RENext->Word1 >> 28) & 0xF; if (RType != 1) report_fatal_error("Expected ARM_RELOC_PAIR after " @@ -864,8 +860,15 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); + unsigned Arch = getArch(); - unsigned Type = getType(RE); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + unsigned Type; + if (isScattered) + Type = (RE->Word0 >> 24) & 0xF; + else + Type = (RE->Word1 >> 28) & 0xF; Result = false; @@ -881,7 +884,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, RelPrev.d.a--; const RelocationEntry *REPrev = getRelocation(RelPrev); - unsigned PrevType = REPrev->Type; + unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 98e28db88d..c846206e6e 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -80,46 +80,6 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } -const MachOObjectFileBase::RelocationEntry * -MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile32Le *O = dyn_cast(this)) - return O->getRelocation(Rel); - const MachOObjectFile64Le *O = dyn_cast(this); - return O->getRelocation(Rel); -} - -bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { - unsigned Arch = getArch(); - return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); -} - -bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->PCRel; - } - return RE->PCRel; -} - -unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->Length; - } - return RE->Length; -} - -unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->Type; - } - return RE->Type; -} - ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; @@ -475,12 +435,16 @@ void advanceTo(T &it, size_t Val) { void MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, raw_string_ostream &fmt) const { + unsigned Arch = getArch(); + bool isScattered = (Arch != Triple::x86_64) && + (RE->Word0 & macho::RF_Scattered); + // Target of a scattered relocation is an address. In the interest of // generating pretty output, scan through the symbol table looking for a // symbol that aligns with that address. If we find one, print it. // Otherwise, we just print the hex address of the target. - if (isScattered(RE)) { - uint32_t Val = RE->SymbolNum; + if (isScattered) { + uint32_t Val = RE->Word1; error_code ec; for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; @@ -522,8 +486,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, } StringRef S; - bool isExtern = RE->External; - uint32_t Val = RE->Address; + bool isExtern = (RE->Word1 >> 27) & 1; + uint32_t Val = RE->Word1 & 0xFFFFFF; if (isExtern) { symbol_iterator SI = begin_symbols(); diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index 96aac231db..b4b876a70b 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -26,17 +26,17 @@ ELF-NEXT: ] MACHO-I386: Relocations [ MACHO-I386-NEXT: Section __text { -MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction -MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts -MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main -MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main +MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 +MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 +MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} MACHO-I386-NEXT: } MACHO-I386-NEXT: ] MACHO-X86-64: Relocations [ MACHO-X86-64-NEXT: Section __text { -MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction -MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts -MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str +MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 +MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 +MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a12d9e4646..a16bca2b19 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -153,10 +153,10 @@ MACHO-I386-NEXT: ] MACHO-I386-NEXT: Reserved1: 0x0 MACHO-I386-NEXT: Reserved2: 0x0 MACHO-I386-NEXT: Relocations [ -MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction -MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts -MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main -MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main +MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 +MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 +MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} MACHO-I386-NEXT: ] MACHO-I386-NEXT: Symbols [ MACHO-I386-NEXT: Symbol { @@ -196,9 +196,9 @@ MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: Relocations [ -MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction -MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts -MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str +MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 +MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 +MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Symbols [ MACHO-X86-64-NEXT: Symbol { diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index b027d40bea..2073ddf463 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -330,28 +330,20 @@ void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; + int64_t Info; StringRef SymbolName; SymbolRef Symbol; if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; + if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; if (error(Symbol.getName(SymbolName))) return; - DataRefImpl DR = RelI->getRawDataRefImpl(); - const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); - bool IsScattered = Obj->isScattered(RE); - raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << Obj->isPCRel(RE) - << " " << Obj->getLength(RE); - if (IsScattered) - OS << " n/a"; - else - OS << " " << RE->External; - OS << " " << RelocName - << " " << IsScattered + << " " << RelocName << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << W.hex(Info) << "\n"; } -- cgit v1.2.3-70-g09d2 From e292347503cd7598429c08f9984ab3e0a44ab8a3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 12 Apr 2013 00:17:33 +0000 Subject: Add 179294 back, but don't use bit fields so that it works on big endian hosts. Original message: Print more information about relocations. With this patch llvm-readobj now prints if a relocation is pcrel, its length, if it is extern and if it is scattered. It also refactors the code a bit to use bit fields instead of shifts and masks all over the place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179345 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 145 +++++++++++++++++------------- lib/Object/MachOObjectFile.cpp | 52 +++++++++-- test/tools/llvm-readobj/relocations.test | 14 +-- test/tools/llvm-readobj/sections-ext.test | 14 +-- tools/llvm-readobj/MachODumper.cpp | 16 +++- 5 files changed, 151 insertions(+), 90 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index b02e1ac100..9b7a07372d 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -112,11 +112,53 @@ namespace MachOFormat { MachOInt32 Reserved3; }; + struct MachOInt24 { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; + } + }; + template struct RelocationEntry { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) - MachOInt32 Word0; - MachOInt32 Word1; + MachOInt32 Address; + MachOInt24 SymbolNum; + uint8_t Bits; + + unsigned getPCRel() const { + return Bits & 0x1; + } + unsigned getLength() const { + return (Bits >> 1) & 0x3; + } + unsigned getExternal() const { + return (Bits >> 3) & 0x1; + } + unsigned getType() const { + return Bits >> 4; + } + }; + + template + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + MachOInt24 Address; + uint8_t Bits; + MachOInt32 Value; + + unsigned getType() const { + return Bits & 0xf; + } + unsigned getLength() const { + return (Bits >> 4) & 0x3; + } + unsigned getPCRel() const { + return (Bits >> 6) & 0x1; + } + unsigned getScattered() const { + return Bits >> 7; + } }; template @@ -206,6 +248,8 @@ public: SymbolTableEntryBase; typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry + ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; typedef MachOFormat::LoadCommand LoadCommand; typedef MachOFormat::Header Header; @@ -243,6 +287,11 @@ public: const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + bool isScattered(const RelocationEntry *RE) const; + bool isPCRel(const RelocationEntry *RE) const; + unsigned getLength(const RelocationEntry *RE) const; + unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); @@ -479,15 +528,12 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, const Section *Sect = getSection(Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); uint64_t RelAddr; - if (isScattered) - RelAddr = RE->Word0 & 0xFFFFFF; + if (isScattered(RE)) + RelAddr = RE->Address & 0xFFFFFF; else - RelAddr = RE->Word0; + RelAddr = RE->Address; Res = SectAddress + RelAddr; return object_error::success; @@ -498,14 +544,10 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - if (isScattered) - Res = RE->Word0 & 0xFFFFFF; + if (isScattered(RE)) + Res = RE->Address & 0xFFFFFF; else - Res = RE->Word0; + Res = RE->Address; return object_error::success; } @@ -514,8 +556,8 @@ error_code MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { const RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->Word1 & 0xffffff; - bool isExtern = (RE->Word1 >> 27) & 1; + uint32_t SymbolIdx = RE->SymbolNum; + bool isExtern = RE->getExternal(); DataRefImpl Sym; moveToNextSymbol(Sym); @@ -535,9 +577,7 @@ template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = RE->Word0; - Res <<= 32; - Res |= RE->Word1; + Res = getType(RE); return object_error::success; } @@ -550,14 +590,8 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned r_type; - if (isScattered) - r_type = (RE->Word0 >> 24) & 0xF; - else - r_type = (RE->Word1 >> 28) & 0xF; + unsigned r_type = getType(RE); switch (Arch) { case Triple::x86: { @@ -650,30 +684,20 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, const RelocationEntry *RE = getRelocation(Rel); unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); + bool IsScattered = isScattered(RE); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; - - bool isPCRel; - if (isScattered) - isPCRel = ((RE->Word0 >> 30) & 1); - else - isPCRel = ((RE->Word1 >> 24) & 1); + unsigned Type = getType(RE); + bool IsPCRel = isPCRel(RE); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. // X86_64 has entirely custom relocation types. if (Arch == Triple::x86_64) { - bool isPCRel = ((RE->Word1 >> 24) & 1); + bool isPCRel = RE->getPCRel(); switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD @@ -691,7 +715,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86_64_SUBTRACTOR must be followed by a relocation of type // X86_64_RELOC_UNSIGNED. // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = (RENext->Word1 >> 28) & 0xF; + unsigned RType = RENext->getType(); if (RType != 0) report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " "X86_64_RELOC_SUBTRACTOR."); @@ -738,12 +762,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); @@ -767,12 +791,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // X86 sect diff's must be followed by a relocation of type // GENERIC_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); @@ -785,7 +809,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, case macho::RIT_Generic_TLV: { printRelocationTargetName(RE, fmt); fmt << "@TLV"; - if (isPCRel) fmt << "P"; + if (IsPCRel) fmt << "P"; break; } default: @@ -798,10 +822,10 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // Half relocations steal a bit from the length field to encode // whether this is an upper16 or a lower16 relocation. bool isUpper; - if (isScattered) - isUpper = (RE->Word0 >> 28) & 1; + if (IsScattered) + isUpper = (RE->Address >> 28) & 1; else - isUpper = (RE->Word1 >> 25) & 1; + isUpper = (RE->getLength() >> 1) & 1; if (isUpper) fmt << ":upper16:("; @@ -816,12 +840,12 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // ARM half relocs must be followed by a relocation of type // ARM_RELOC_PAIR. bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Word0 & macho::RF_Scattered); + (RENext->Address & macho::RF_Scattered); unsigned RType; if (isNextScattered) - RType = (RENext->Word0 >> 24) & 0xF; + RType = (RENext->Address >> 24) & 0xF; else - RType = (RENext->Word1 >> 28) & 0xF; + RType = RENext->getType(); if (RType != 1) report_fatal_error("Expected ARM_RELOC_PAIR after " @@ -860,15 +884,8 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - unsigned Type; - if (isScattered) - Type = (RE->Word0 >> 24) & 0xF; - else - Type = (RE->Word1 >> 28) & 0xF; + unsigned Type = getType(RE); Result = false; @@ -884,7 +901,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, RelPrev.d.a--; const RelocationEntry *REPrev = getRelocation(RelPrev); - unsigned PrevType = (REPrev->Word1 >> 28) & 0xF; + unsigned PrevType = REPrev->getType(); if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index c846206e6e..627e7485a6 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -80,6 +80,46 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } +const MachOObjectFileBase::RelocationEntry * +MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { + if (const MachOObjectFile32Le *O = dyn_cast(this)) + return O->getRelocation(Rel); + const MachOObjectFile64Le *O = dyn_cast(this); + return O->getRelocation(Rel); +} + +bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { + unsigned Arch = getArch(); + return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); +} + +bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getPCRel(); + } + return RE->getPCRel(); +} + +unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getLength(); + } + return RE->getLength(); +} + +unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { + if (isScattered(RE)) { + const ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getType(); + } + return RE->getType(); +} + ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; @@ -435,16 +475,12 @@ void advanceTo(T &it, size_t Val) { void MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, raw_string_ostream &fmt) const { - unsigned Arch = getArch(); - bool isScattered = (Arch != Triple::x86_64) && - (RE->Word0 & macho::RF_Scattered); - // Target of a scattered relocation is an address. In the interest of // generating pretty output, scan through the symbol table looking for a // symbol that aligns with that address. If we find one, print it. // Otherwise, we just print the hex address of the target. - if (isScattered) { - uint32_t Val = RE->Word1; + if (isScattered(RE)) { + uint32_t Val = RE->SymbolNum; error_code ec; for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; @@ -486,8 +522,8 @@ MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, } StringRef S; - bool isExtern = (RE->Word1 >> 27) & 1; - uint32_t Val = RE->Word1 & 0xFFFFFF; + bool isExtern = RE->getExternal(); + uint32_t Val = RE->Address; if (isExtern) { symbol_iterator SI = begin_symbols(); diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index b4b876a70b..96aac231db 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -26,17 +26,17 @@ ELF-NEXT: ] MACHO-I386: Relocations [ MACHO-I386-NEXT: Section __text { -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: } MACHO-I386-NEXT: ] MACHO-X86-64: Relocations [ MACHO-X86-64-NEXT: Section __text { -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a16bca2b19..a12d9e4646 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -153,10 +153,10 @@ MACHO-I386-NEXT: ] MACHO-I386-NEXT: Reserved1: 0x0 MACHO-I386-NEXT: Reserved2: 0x0 MACHO-I386-NEXT: Relocations [ -MACHO-I386-NEXT: 0x18 GENERIC_RELOC_VANILLA _SomeOtherFunction 0x0 -MACHO-I386-NEXT: 0x13 GENERIC_RELOC_VANILLA _puts 0x0 -MACHO-I386-NEXT: 0xB GENERIC_RELOC_LOCAL_SECTDIFF _main 0x{{[0-9A-F]+}} -MACHO-I386-NEXT: 0x0 GENERIC_RELOC_PAIR _main 0x{{[0-9A-F]+}} +MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction +MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main MACHO-I386-NEXT: ] MACHO-I386-NEXT: Symbols [ MACHO-I386-NEXT: Symbol { @@ -196,9 +196,9 @@ MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: Relocations [ -MACHO-X86-64-NEXT: 0xE X86_64_RELOC_BRANCH _SomeOtherFunction 0x0 -MACHO-X86-64-NEXT: 0x9 X86_64_RELOC_BRANCH _puts 0x0 -MACHO-X86-64-NEXT: 0x4 X86_64_RELOC_SIGNED L_.str 0x0 +MACHO-X86-64-NEXT: 0xE 1 2 1 X86_64_RELOC_BRANCH 0 _SomeOtherFunction +MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts +MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: ] MACHO-X86-64-NEXT: Symbols [ MACHO-X86-64-NEXT: Symbol { diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 2073ddf463..a13593b448 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -330,20 +330,28 @@ void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; - int64_t Info; StringRef SymbolName; SymbolRef Symbol; if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; - if (error(RelI->getAdditionalInfo(Info))) return; if (error(RelI->getSymbol(Symbol))) return; if (error(Symbol.getName(SymbolName))) return; + DataRefImpl DR = RelI->getRawDataRefImpl(); + const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); + bool IsScattered = Obj->isScattered(RE); + raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << RelocName + << " " << Obj->isPCRel(RE) + << " " << Obj->getLength(RE); + if (IsScattered) + OS << " n/a"; + else + OS << " " << RE->getExternal(); + OS << " " << RelocName + << " " << IsScattered << " " << (SymbolName.size() > 0 ? SymbolName : "-") - << " " << W.hex(Info) << "\n"; } -- cgit v1.2.3-70-g09d2 From da2a2372c6ae715befae7f086afe769dd80814f3 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 13 Apr 2013 01:45:40 +0000 Subject: Finish templating MachObjectFile over endianness. We are now able to handle big endian macho files in llvm-readobject. Thanks to David Fang for providing the object files. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179440 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 783 ++++++++++++++++++--- lib/Object/MachOObjectFile.cpp | 432 +----------- .../llvm-readobj/Inputs/trivial.obj.macho-ppc | Bin 0 -> 844 bytes .../llvm-readobj/Inputs/trivial.obj.macho-ppc64 | Bin 0 -> 956 bytes test/tools/llvm-readobj/relocations.test | 42 ++ test/tools/llvm-readobj/sections-ext.test | 313 ++++++++ test/tools/llvm-readobj/sections.test | 178 +++++ tools/llvm-objdump/MachODump.cpp | 48 +- tools/llvm-objdump/llvm-objdump.cpp | 18 +- tools/llvm-readobj/MachODumper.cpp | 132 ++-- 10 files changed, 1353 insertions(+), 593 deletions(-) create mode 100644 test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc create mode 100644 test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 9b7a07372d..33e10ffbbd 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -20,7 +20,9 @@ #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" @@ -35,6 +37,25 @@ struct MachOType { static const bool Is64Bits = B; }; +template +struct MachOInt24Impl; + +template<> +struct MachOInt24Impl { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; + } +}; + +template<> +struct MachOInt24Impl { + uint8_t bytes[3]; + operator uint32_t() const { + return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2]; + } +}; + template struct MachODataTypeTypedefHelperCommon { typedef support::detail::packed_endian_specific_integral @@ -43,12 +64,14 @@ struct MachODataTypeTypedefHelperCommon { MachOInt32; typedef support::detail::packed_endian_specific_integral MachOInt64; + typedef MachOInt24Impl MachOInt24; }; #define LLVM_MACHOB_IMPORT_TYPES(E) \ typedef typename MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \ typedef typename MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; +typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \ +typedef typename MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24; template struct MachODataTypeTypedefHelper; @@ -120,8 +143,11 @@ namespace MachOFormat { }; template - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct RelocationEntry; + + template<> + struct RelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt32 Address; MachOInt24 SymbolNum; uint8_t Bits; @@ -140,9 +166,33 @@ namespace MachOFormat { } }; + template<> + struct RelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::big) + MachOInt32 Address; + MachOInt24 SymbolNum; + uint8_t Bits; + + unsigned getType() const { + return Bits &0xf; + } + unsigned getExternal() const { + return (Bits >> 4) & 0x1; + } + unsigned getLength() const { + return (Bits >> 5) & 0x3; + } + unsigned getPCRel() const { + return Bits >> 7; + } + }; + template - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) + struct ScatteredRelocationEntry; + + template<> + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::little) MachOInt24 Address; uint8_t Bits; MachOInt32 Value; @@ -161,6 +211,26 @@ namespace MachOFormat { } }; + template<> + struct ScatteredRelocationEntry { + LLVM_MACHOB_IMPORT_TYPES(support::big) + uint8_t Bits; + unsigned getType() const { + return Bits & 0xf; + } + unsigned getLength() const { + return (Bits >> 4) & 0x3; + } + unsigned getPCRel() const { + return (Bits >> 6) & 0x1; + } + unsigned getScattered() const { + return Bits >> 7; + } + MachOInt24 Address; + MachOInt32 Value; + }; + template struct SymbolTableEntryBase { LLVM_MACHOB_IMPORT_TYPES(TargetEndianness) @@ -244,69 +314,32 @@ namespace MachOFormat { class MachOObjectFileBase : public ObjectFile { public: - typedef MachOFormat::SymbolTableEntryBase - SymbolTableEntryBase; - typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; - typedef MachOFormat::RelocationEntry RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry - ScatteredRelocationEntry; typedef MachOFormat::SectionBase SectionBase; - typedef MachOFormat::LoadCommand LoadCommand; - typedef MachOFormat::Header Header; - typedef MachOFormat::LinkeditDataLoadCommand - LinkeditDataLoadCommand; - MachOObjectFileBase(MemoryBuffer *Object, bool Is64Bits, error_code &ec); + MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - virtual symbol_iterator begin_symbols() const; - virtual symbol_iterator end_symbols() const; virtual symbol_iterator begin_dynamic_symbols() const; virtual symbol_iterator end_dynamic_symbols() const; virtual library_iterator begin_libraries_needed() const; virtual library_iterator end_libraries_needed() const; - virtual section_iterator end_sections() const; virtual uint8_t getBytesInAddress() const; - virtual StringRef getFileFormatName() const; - virtual unsigned getArch() const; virtual StringRef getLoadName() const; - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. - StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - - // Names are stored as 16 bytes. These returns the raw 16 bytes without - // interpreting them as a C string. - ArrayRef getSectionRawName(DataRefImpl Sec) const; - ArrayRefgetSectionRawFinalSegmentName(DataRefImpl Sec) const; - bool is64Bit() const; - const LoadCommand *getLoadCommandInfo(unsigned Index) const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - const Header *getHeader() const; unsigned getHeaderSize() const; StringRef getData(size_t Offset, size_t Size) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isScattered(const RelocationEntry *RE) const; - bool isPCRel(const RelocationEntry *RE) const; - unsigned getLength(const RelocationEntry *RE) const; - unsigned getType(const RelocationEntry *RE) const; static inline bool classof(const Binary *v) { return v->isMachO(); } protected: - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const; + StringRef parseSegmentOrSectionName(const char *P) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, @@ -327,17 +360,75 @@ protected: typedef SmallVector SectionList; SectionList Sections; +}; + +template +class MachOObjectFileMiddle : public MachOObjectFileBase { +public: + + typedef MachOFormat::SymbolTableEntryBase + SymbolTableEntryBase; + typedef MachOFormat::LinkeditDataLoadCommand + LinkeditDataLoadCommand; + typedef MachOFormat::Header Header; + typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; + typedef MachOFormat::RelocationEntry RelocationEntry; + typedef MachOFormat::ScatteredRelocationEntry + ScatteredRelocationEntry; + typedef MachOFormat::LoadCommand LoadCommand; + + MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec); + + const Header *getHeader() const; + const LoadCommand *getLoadCommandInfo(unsigned Index) const; + const RelocationEntry *getRelocation(DataRefImpl Rel) const; + bool isRelocationScattered(const RelocationEntry *RE) const; + bool isRelocationPCRel(const RelocationEntry *RE) const; + unsigned getRelocationLength(const RelocationEntry *RE) const; + unsigned getRelocationTypeImpl(const RelocationEntry *RE) const; void moveToNextSymbol(DataRefImpl &DRI) const; void printRelocationTargetName(const RelocationEntry *RE, raw_string_ostream &fmt) const; const SectionBase *getSectionBase(DataRefImpl DRI) const; const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; + unsigned getCPUType() const; + + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in in the final object. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; + + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef getSectionRawName(DataRefImpl Sec) const; + ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; + + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual symbol_iterator begin_symbols() const; + virtual unsigned getArch() const; + virtual StringRef getFileFormatName() const; + virtual symbol_iterator end_symbols() const; + virtual section_iterator end_sections() const; + + static bool classof(const Binary *v); private: + // Helper to advance a section or symbol iterator multiple increments at a + // time. + template + static error_code advance(T &it, size_t Val); - const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const; + template + static void advanceTo(T &it, size_t Val); }; template @@ -369,11 +460,17 @@ struct MachOObjectFileHelper > : }; template -class MachOObjectFile : public MachOObjectFileBase { +class MachOObjectFile : public MachOObjectFileMiddle { public: static const endianness TargetEndianness = MachOT::TargetEndianness; static const bool Is64Bits = MachOT::Is64Bits; + typedef MachOObjectFileMiddle Base; + typedef typename Base::RelocationEntry RelocationEntry; + typedef typename Base::SectionBase SectionBase; + typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase; + typedef typename Base::LoadCommand LoadCommand; + typedef MachOObjectFileHelper Helper; static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; @@ -413,15 +510,491 @@ public: void moveToNextSection(DataRefImpl &DRI) const; }; +typedef MachOObjectFileMiddle MachOObjectFileLE; +typedef MachOObjectFileMiddle MachOObjectFileBE; + +typedef MachOObjectFile > + MachOObjectFileLE32; +typedef MachOObjectFile > + MachOObjectFileBE32; +typedef MachOObjectFile > + MachOObjectFileLE64; +typedef MachOObjectFile > + MachOObjectFileBE64; + +template +MachOObjectFileMiddle::MachOObjectFileMiddle(MemoryBuffer *O, + bool Is64Bits, + error_code &ec) : + MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) { +} + +template +const typename MachOObjectFileMiddle::SymbolTableEntryBase * +MachOObjectFileMiddle::getSymbolTableEntryBase(DataRefImpl DRI) const { + const LoadCommand *L = getLoadCommandInfo(DRI.d.a); + const SymtabLoadCommand *S = reinterpret_cast(L); + + unsigned Index = DRI.d.b; + + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(MachOObjectFileLE64::SymbolTableEntry) : + sizeof(MachOObjectFileLE32::SymbolTableEntry); + + uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize; + StringRef Data = getData(Offset, SymbolTableEntrySize); + return reinterpret_cast(Data.data()); +} + +template +const typename MachOObjectFileMiddle::Header * +MachOObjectFileMiddle::getHeader() const { + StringRef Data = getData(0, sizeof(Header)); + return reinterpret_cast(Data.data()); +} + +template +const typename MachOObjectFileMiddle::LoadCommand * +MachOObjectFileMiddle::getLoadCommandInfo(unsigned Index) const { + assert(Index < getHeader()->NumLoadCommands); + uint64_t Offset; + uint64_t NewOffset = getHeaderSize(); + const LoadCommand *Load; + unsigned I = 0; + do { + Offset = NewOffset; + StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand)); + Load = reinterpret_cast(Data.data()); + NewOffset = Offset + Load->Size; + ++I; + } while (I != Index + 1); + + return reinterpret_cast(Load); +} + +template +const typename MachOObjectFileMiddle::RelocationEntry * +MachOObjectFileMiddle::getRelocation(DataRefImpl Rel) const { + if (const MachOObjectFile > *O = + dyn_cast > >(this)) + return O->getRelocation(Rel); + + const MachOObjectFile > *O = + cast > >(this); + return O->getRelocation(Rel); +} + +template +bool +MachOObjectFileMiddle::isRelocationScattered(const RelocationEntry *RE) + const { + if (this->getCPUType() == llvm::MachO::CPUTypeX86_64) + return false; + return RE->Address & macho::RF_Scattered; +} + +template +bool +MachOObjectFileMiddle::isRelocationPCRel(const RelocationEntry *RE) const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getPCRel(); + } + return RE->getPCRel(); +} + +template +unsigned +MachOObjectFileMiddle::getRelocationLength(const RelocationEntry *RE) const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getLength(); + } + return RE->getLength(); +} + +template +unsigned +MachOObjectFileMiddle::getRelocationTypeImpl(const RelocationEntry *RE) + const { + typedef MachOObjectFileMiddle ObjType; + if (isRelocationScattered(RE)) { + const ObjType::ScatteredRelocationEntry *SRE = + reinterpret_cast(RE); + return SRE->getType(); + } + return RE->getType(); +} + +// Helper to advance a section or symbol iterator multiple increments at a time. +template +template +error_code MachOObjectFileMiddle::advance(T &it, size_t Val) { + error_code ec; + while (Val--) { + it.increment(ec); + } + return ec; +} + +template +template +void MachOObjectFileMiddle::advanceTo(T &it, size_t Val) { + if (error_code ec = advance(it, Val)) + report_fatal_error(ec.message()); +} + +template +void +MachOObjectFileMiddle::printRelocationTargetName(const RelocationEntry *RE, + raw_string_ostream &fmt) const { + bool IsScattered = isRelocationScattered(RE); + + // Target of a scattered relocation is an address. In the interest of + // generating pretty output, scan through the symbol table looking for a + // symbol that aligns with that address. If we find one, print it. + // Otherwise, we just print the hex address of the target. + if (IsScattered) { + uint32_t Val = RE->SymbolNum; + + error_code ec; + for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; + SI.increment(ec)) { + if (ec) report_fatal_error(ec.message()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + // If we couldn't find a symbol that this relocation refers to, try + // to find a section beginning instead. + for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; + SI.increment(ec)) { + if (ec) report_fatal_error(ec.message()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = RE->getExternal(); + uint64_t Val = RE->Address; + + if (isExtern) { + symbol_iterator SI = begin_symbols(); + advanceTo(SI, Val); + SI->getName(S); + } else { + section_iterator SI = begin_sections(); + advanceTo(SI, Val); + SI->getName(S); + } + + fmt << S; +} + +template +const typename MachOObjectFileMiddle::SectionBase * +MachOObjectFileMiddle::getSectionBase(DataRefImpl DRI) const { + uintptr_t CommandAddr = + reinterpret_cast(getLoadCommandInfo(DRI.d.a)); + + bool Is64 = is64Bit(); + unsigned SegmentLoadSize = + Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) : + sizeof(MachOObjectFileLE32::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) : + sizeof(MachOObjectFileLE32::Section); + + uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; + return reinterpret_cast(SectionAddr); +} + +template +unsigned MachOObjectFileMiddle::getCPUType() const { + return getHeader()->CPUType; +} + +template +void MachOObjectFileMiddle::moveToNextSymbol(DataRefImpl &DRI) const { + uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + while (DRI.d.a < LoadCommandCount) { + const LoadCommand *L = getLoadCommandInfo(DRI.d.a); + if (L->Type == macho::LCT_Symtab) { + const SymtabLoadCommand *S = + reinterpret_cast(L); + if (DRI.d.b < S->NumSymbolTableEntries) + return; + } + + DRI.d.a++; + DRI.d.b = 0; + } +} + +template +StringRef +MachOObjectFileMiddle::getSectionFinalSegmentName(DataRefImpl Sec) const { + ArrayRef Raw = getSectionRawFinalSegmentName(Sec); + return parseSegmentOrSectionName(Raw.data()); +} + +template +ArrayRef +MachOObjectFileMiddle::getSectionRawName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); + return ArrayRef(Base->Name); +} + +template +ArrayRef +MachOObjectFileMiddle::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const SectionBase *Base = getSectionBase(Sec); + return ArrayRef(Base->SegmentName); +} + +template +error_code MachOObjectFileMiddle::getSymbolFlags(DataRefImpl DRI, + uint32_t &Result) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); + + uint8_t MachOType = Entry->Type; + uint16_t MachOFlags = Entry->Flags; + + // TODO: Correctly set SF_ThreadLocal + Result = SymbolRef::SF_None; + + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) + Result |= SymbolRef::SF_Undefined; + + if (MachOFlags & macho::STF_StabsEntryMask) + Result |= SymbolRef::SF_FormatSpecific; + + if (MachOType & MachO::NlistMaskExternal) { + Result |= SymbolRef::SF_Global; + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) + Result |= SymbolRef::SF_Common; + } + + if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) + Result |= SymbolRef::SF_Weak; + + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) + Result |= SymbolRef::SF_Absolute; + + return object_error::success; +} + +template +error_code MachOObjectFileMiddle::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + uint8_t n_type = Entry->Type; + + Res = SymbolRef::ST_Other; + + // If this is a STAB debugging symbol, we can do nothing more. + if (n_type & MachO::NlistMaskStab) { + Res = SymbolRef::ST_Debug; + return object_error::success; + } + + switch (n_type & MachO::NlistMaskType) { + case MachO::NListTypeUndefined : + Res = SymbolRef::ST_Unknown; + break; + case MachO::NListTypeSection : + Res = SymbolRef::ST_Function; + break; + } + return object_error::success; +} + +template +error_code MachOObjectFileMiddle::getSymbolName(DataRefImpl Symb, + StringRef &Res) const { + const LoadCommand *L = getLoadCommandInfo(Symb.d.a); + const SymtabLoadCommand *S = reinterpret_cast(L); + StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize); + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + const char *Start = &StringTable.data()[Entry->StringIndex]; + Res = StringRef(Start); + return object_error::success; +} + +template +error_code +MachOObjectFileMiddle::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + uint8_t index = Entry->SectionIndex; + + if (index == 0) + Res = end_sections(); + else + Res = section_iterator(SectionRef(Sections[index-1], this)); + + return object_error::success; +} + + +template +error_code MachOObjectFileMiddle::getSymbolNMTypeChar(DataRefImpl Symb, + char &Res) const { + const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); + uint8_t Type = Entry->Type; + uint16_t Flags = Entry->Flags; + + char Char; + switch (Type & macho::STF_TypeMask) { + case macho::STT_Undefined: + Char = 'u'; + break; + case macho::STT_Absolute: + case macho::STT_Section: + Char = 's'; + break; + default: + Char = '?'; + break; + } + + if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) + Char = toupper(static_cast(Char)); + Res = Char; + return object_error::success; +} + +template +error_code +MachOObjectFileMiddle::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ArrayRef Raw = getSectionRawName(Sec); + Result = parseSegmentOrSectionName(Raw.data()); + return object_error::success; +} + +template +error_code MachOObjectFileMiddle::getSymbolNext(DataRefImpl Symb, + SymbolRef &Res) const { + Symb.d.b++; + moveToNextSymbol(Symb); + Res = SymbolRef(Symb, this); + return object_error::success; +} + +template +symbol_iterator MachOObjectFileMiddle::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + moveToNextSymbol(DRI); + return symbol_iterator(SymbolRef(DRI, this)); +} + +template +unsigned MachOObjectFileMiddle::getArch() const { + switch (getCPUType()) { + case llvm::MachO::CPUTypeI386: + return Triple::x86; + case llvm::MachO::CPUTypeX86_64: + return Triple::x86_64; + case llvm::MachO::CPUTypeARM: + return Triple::arm; + case llvm::MachO::CPUTypePowerPC: + return Triple::ppc; + case llvm::MachO::CPUTypePowerPC64: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +template +StringRef MachOObjectFileMiddle::getFileFormatName() const { + unsigned CPUType = getCPUType(); + if (!is64Bit()) { + switch (CPUType) { + case llvm::MachO::CPUTypeI386: + return "Mach-O 32-bit i386"; + case llvm::MachO::CPUTypeARM: + return "Mach-O arm"; + case llvm::MachO::CPUTypePowerPC: + return "Mach-O 32-bit ppc"; + default: + assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; + } + } + + // Make sure the cpu type has the correct mask. + assert((CPUType & llvm::MachO::CPUArchABI64) + == llvm::MachO::CPUArchABI64 && + "32-bit object file when we're 64-bit?"); + + switch (CPUType) { + case llvm::MachO::CPUTypeX86_64: + return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPUTypePowerPC64: + return "Mach-O 64-bit ppc64"; + default: + return "Mach-O 64-bit unknown"; + } +} + +template +symbol_iterator MachOObjectFileMiddle::end_symbols() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return symbol_iterator(SymbolRef(DRI, this)); +} + +template +section_iterator MachOObjectFileMiddle::end_sections() const { + DataRefImpl DRI; + DRI.d.a = getHeader()->NumLoadCommands; + return section_iterator(SectionRef(DRI, this)); +} + +template +bool MachOObjectFileMiddle::classof(const Binary *v) { + return isa > >(v) || + isa > >(v); +} + template MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code &ec) : - MachOObjectFileBase(Object, Is64Bits, ec) { + MachOObjectFileMiddle(Object, Is64Bits, ec) { DataRefImpl DRI; moveToNextSection(DRI); - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - Sections.push_back(DRI); + this->Sections.push_back(DRI); DRI.d.b++; moveToNextSection(DRI); } @@ -429,30 +1002,31 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, template bool MachOObjectFile::classof(const Binary *v) { - return v->getType() == getMachOType(true, Is64Bits); + return v->getType() == + Base::getMachOType(TargetEndianness == support::little, Is64Bits); } template const typename MachOObjectFile::Section * MachOObjectFile::getSection(DataRefImpl DRI) const { - const SectionBase *Addr = getSectionBase(DRI); + const SectionBase *Addr = this->getSectionBase(DRI); return reinterpret_cast(Addr); } template const typename MachOObjectFile::SymbolTableEntry * MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const SymbolTableEntryBase *Base = getSymbolTableEntryBase(DRI); + const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI); return reinterpret_cast(Base); } template const typename MachOObjectFile::RelocationEntry * MachOObjectFile::getRelocation(DataRefImpl Rel) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint32_t RelOffset = Sect->RelocationTableOffset; uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); - StringRef Data = getData(Offset, sizeof(RelocationEntry)); + StringRef Data = this->getData(Offset, sizeof(RelocationEntry)); return reinterpret_cast(Data.data()); } @@ -479,7 +1053,7 @@ error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { const Section *Sect = getSection(Sec); - Res = getData(Sect->Offset, Sect->Size); + Res = this->getData(Sect->Offset, Sect->Size); return object_error::success; } @@ -517,7 +1091,7 @@ MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { uint32_t LastReloc = Sect->NumRelocationTableEntries; DataRefImpl Ret; Ret.d.a = LastReloc; - Ret.d.b = getSectionIndex(Sec); + Ret.d.b = this->getSectionIndex(Sec); return relocation_iterator(RelocationRef(Ret, this)); } @@ -525,12 +1099,12 @@ template error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { - const Section *Sect = getSection(Sections[Rel.d.b]); + const Section *Sect = getSection(this->Sections[Rel.d.b]); uint64_t SectAddress = Sect->Address; const RelocationEntry *RE = getRelocation(Rel); uint64_t RelAddr; - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) RelAddr = RE->Address & 0xFFFFFF; else RelAddr = RE->Address; @@ -544,7 +1118,7 @@ error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - if (isScattered(RE)) + if (this->isRelocationScattered(RE)) Res = RE->Address & 0xFFFFFF; else Res = RE->Address; @@ -560,12 +1134,12 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, bool isExtern = RE->getExternal(); DataRefImpl Sym; - moveToNextSymbol(Sym); + this->moveToNextSymbol(Sym); if (isExtern) { for (unsigned i = 0; i < SymbolIdx; i++) { Sym.d.b++; - moveToNextSymbol(Sym); - assert(Sym.d.a < getHeader()->NumLoadCommands && + this->moveToNextSymbol(Sym); + assert(Sym.d.a < this->getHeader()->NumLoadCommands && "Relocation symbol index out of range!"); } } @@ -577,7 +1151,7 @@ template error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, uint64_t &Res) const { const RelocationEntry *RE = getRelocation(Rel); - Res = getType(RE); + Res = this->getRelocationTypeImpl(RE); return object_error::success; } @@ -589,9 +1163,9 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, StringRef res; const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); + unsigned Arch = this->getArch(); - unsigned r_type = getType(RE); + unsigned r_type = this->getRelocationTypeImpl(RE); switch (Arch) { case Triple::x86: { @@ -683,14 +1257,14 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - bool IsScattered = isScattered(RE); + unsigned Arch = this->getArch(); + bool IsScattered = this->isRelocationScattered(RE); std::string fmtbuf; raw_string_ostream fmt(fmtbuf); - unsigned Type = getType(RE); - bool IsPCRel = isPCRel(RE); + unsigned Type = this->getRelocationTypeImpl(RE); + bool IsPCRel = this->isRelocationPCRel(RE); // Determine any addends that should be displayed with the relocation. // These require decoding the relocation type, which is triple-specific. @@ -702,7 +1276,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, switch (Type) { case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@GOT"; if (isPCRel) fmt << "PCREL"; break; @@ -722,30 +1296,30 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // The X86_64_RELOC_UNSIGNED contains the minuend symbol, // X86_64_SUBTRACTOR contains to the subtrahend. - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); fmt << "-"; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } case macho::RIT_X86_64_TLV: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (isPCRel) fmt << "P"; break; case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-1"; break; case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-2"; break; case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-4"; break; default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); break; } // X86 and ARM share some relocation types in common. @@ -772,9 +1346,9 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } } @@ -801,19 +1375,19 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, report_fatal_error("Expected GENERIC_RELOC_PAIR after " "GENERIC_RELOC_LOCAL_SECTDIFF."); - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); break; } case macho::RIT_Generic_TLV: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt << "@TLV"; if (IsPCRel) fmt << "P"; break; } default: - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } else { // ARM-specific relocations switch (Type) { @@ -831,7 +1405,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, fmt << ":upper16:("; else fmt << ":lower16:("; - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); DataRefImpl RelNext = Rel; RelNext.d.a++; @@ -860,19 +1434,19 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, // symbol/section pointer of the follow-on relocation. if (Type == macho::RIT_ARM_HalfDifference) { fmt << "-"; - printRelocationTargetName(RENext, fmt); + this->printRelocationTargetName(RENext, fmt); } fmt << ")"; break; } default: { - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); } } } } else - printRelocationTargetName(RE, fmt); + this->printRelocationTargetName(RE, fmt); fmt.flush(); Result.append(fmtbuf.begin(), fmtbuf.end()); @@ -884,8 +1458,8 @@ error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = getArch(); - unsigned Type = getType(RE); + unsigned Arch = this->getArch(); + unsigned Type = this->getRelocationTypeImpl(RE); Result = false; @@ -899,7 +1473,7 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { DataRefImpl RelPrev = Rel; RelPrev.d.a--; - const RelocationEntry *REPrev = getRelocation(RelPrev); + const RelocationEntry *REPrev = this->getRelocation(RelPrev); unsigned PrevType = REPrev->getType(); @@ -917,7 +1491,8 @@ MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); Res = Entry->Value; if (Entry->SectionIndex) { - const Section *Sec = getSection(Sections[Entry->SectionIndex-1]); + const Section *Sec = + this->getSection(this->Sections[Entry->SectionIndex-1]); Res += Sec->Offset - Sec->Address; } @@ -930,7 +1505,7 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { SymbolRef::Type ST; - getSymbolType(Symb, ST); + this->getSymbolType(Symb, ST); if (ST == SymbolRef::ST_Unknown) { Result = false; return object_error::success; @@ -959,7 +1534,7 @@ error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, template error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; uint64_t BeginOffset; uint64_t EndOffset = 0; uint8_t SectionIndex; @@ -969,7 +1544,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, SectionIndex = Entry->SectionIndex; if (!SectionIndex) { uint32_t flags = SymbolRef::SF_None; - getSymbolFlags(DRI, flags); + this->getSymbolFlags(DRI, flags); if (flags & SymbolRef::SF_Common) Result = Entry->Value; else @@ -981,7 +1556,7 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, DRI.d.b = 0; uint32_t Command = DRI.d.a; while (Command == DRI.d.a) { - moveToNextSymbol(DRI); + this->moveToNextSymbol(DRI); if (DRI.d.a < LoadCommandCount) { Entry = getSymbolTableEntry(DRI); if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) @@ -992,8 +1567,8 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, } if (!EndOffset) { uint64_t Size; - getSectionSize(Sections[SectionIndex-1], Size); - getSectionAddress(Sections[SectionIndex-1], EndOffset); + this->getSectionSize(this->Sections[SectionIndex-1], Size); + this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset); EndOffset += Size; } Result = EndOffset - BeginOffset; @@ -1018,9 +1593,9 @@ section_iterator MachOObjectFile::begin_sections() const { template void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; + uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); + const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a); if (Command->Type == SegmentLoadType) { const SegmentLoadCommand *SegmentLoadCmd = reinterpret_cast(Command); @@ -1033,10 +1608,6 @@ void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { } } - typedef MachOObjectFile > - MachOObjectFile32Le; - typedef MachOObjectFile > - MachOObjectFile64Le; } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 627e7485a6..192e7555b4 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -29,30 +29,14 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, bool Is64bits, +MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, + bool IsLittleEndian, bool Is64bits, error_code &ec) - : ObjectFile(getMachOType(true, Is64bits), Object) { + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) { } bool MachOObjectFileBase::is64Bit() const { - return isa(this); -} - -const MachOObjectFileBase::LoadCommand * -MachOObjectFileBase::getLoadCommandInfo(unsigned Index) const { - uint64_t Offset; - uint64_t NewOffset = getHeaderSize(); - const LoadCommand *Load; - unsigned I = 0; - do { - Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(LoadCommand)); - Load = reinterpret_cast(Data.data()); - NewOffset = Offset + Load->Size; - ++I; - } while (I != Index + 1); - - return Load; + return isa(this) || isa(this); } void MachOObjectFileBase::ReadULEB128s(uint64_t Index, @@ -67,11 +51,6 @@ void MachOObjectFileBase::ReadULEB128s(uint64_t Index, } } -const MachOObjectFileBase::Header *MachOObjectFileBase::getHeader() const { - StringRef Data = getData(0, sizeof(Header)); - return reinterpret_cast(Data.data()); -} - unsigned MachOObjectFileBase::getHeaderSize() const { return is64Bit() ? macho::Header64Size : macho::Header32Size; } @@ -80,55 +59,21 @@ StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { return ObjectFile::getData().substr(Offset, Size); } -const MachOObjectFileBase::RelocationEntry * -MachOObjectFileBase::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile32Le *O = dyn_cast(this)) - return O->getRelocation(Rel); - const MachOObjectFile64Le *O = dyn_cast(this); - return O->getRelocation(Rel); -} - -bool MachOObjectFileBase::isScattered(const RelocationEntry *RE) const { - unsigned Arch = getArch(); - return (Arch != Triple::x86_64) && (RE->Address & macho::RF_Scattered); -} - -bool MachOObjectFileBase::isPCRel(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getPCRel(); - } - return RE->getPCRel(); -} - -unsigned MachOObjectFileBase::getLength(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getLength(); - } - return RE->getLength(); -} - -unsigned MachOObjectFileBase::getType(const RelocationEntry *RE) const { - if (isScattered(RE)) { - const ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->getType(); - } - return RE->getType(); -} - ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { StringRef Magic = Buffer->getBuffer().slice(0, 4); error_code ec; - bool Is64Bits = Magic == "\xFE\xED\xFA\xCF" || Magic == "\xCF\xFA\xED\xFE"; ObjectFile *Ret; - if (Is64Bits) - Ret = new MachOObjectFile64Le(Buffer, ec); + if (Magic == "\xFE\xED\xFA\xCE") + Ret = new MachOObjectFileBE32(Buffer, ec); + else if (Magic == "\xCE\xFA\xED\xFE") + Ret = new MachOObjectFileLE32(Buffer, ec); + else if (Magic == "\xFE\xED\xFA\xCF") + Ret = new MachOObjectFileBE64(Buffer, ec); + else if (Magic == "\xCF\xFA\xED\xFE") + Ret = new MachOObjectFileLE64(Buffer, ec); else - Ret = new MachOObjectFile32Le(Buffer, ec); + return NULL; + if (ec) return NULL; return Ret; @@ -136,183 +81,11 @@ ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { /*===-- Symbols -----------------------------------------------------------===*/ -void MachOObjectFileBase::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - if (Command->Type == macho::LCT_Symtab) { - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - if (DRI.d.b < SymtabLoadCmd->NumSymbolTableEntries) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - return getSymbolTableEntryBase(DRI, SymtabLoadCmd); -} - -const MachOObjectFileBase::SymbolTableEntryBase * -MachOObjectFileBase::getSymbolTableEntryBase(DataRefImpl DRI, - const SymtabLoadCommand *SymtabLoadCmd) const { - uint64_t SymbolTableOffset = SymtabLoadCmd->SymbolTableOffset; - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFile64Le::SymbolTableEntry) : - sizeof(MachOObjectFile32Le::SymbolTableEntry); - - uint64_t Offset = SymbolTableOffset + Index * SymbolTableEntrySize; - StringRef Data = getData(Offset, SymbolTableEntrySize); - return reinterpret_cast(Data.data()); -} - -error_code MachOObjectFileBase::getSymbolNext(DataRefImpl DRI, - SymbolRef &Result) const { - DRI.d.b++; - moveToNextSymbol(DRI); - Result = SymbolRef(DRI, this); - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolName(DataRefImpl DRI, - StringRef &Result) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *SymtabLoadCmd = - reinterpret_cast(Command); - - StringRef StringTable = getData(SymtabLoadCmd->StringTableOffset, - SymtabLoadCmd->StringTableSize); - - const SymbolTableEntryBase *Entry = - getSymbolTableEntryBase(DRI, SymtabLoadCmd); - uint32_t StringIndex = Entry->StringIndex; - - const char *Start = &StringTable.data()[StringIndex]; - Result = StringRef(Start); - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolNMTypeChar(DataRefImpl DRI, - char &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - uint8_t Type = Entry->Type; - uint16_t Flags = Entry->Flags; - - char Char; - switch (Type & macho::STF_TypeMask) { - case macho::STT_Undefined: - Char = 'u'; - break; - case macho::STT_Absolute: - case macho::STT_Section: - Char = 's'; - break; - default: - Char = '?'; - break; - } - - if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) - Char = toupper(static_cast(Char)); - Result = Char; - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - uint8_t MachOType = Entry->Type; - uint16_t MachOFlags = Entry->Flags; - - // TODO: Correctly set SF_ThreadLocal - Result = SymbolRef::SF_None; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Undefined; - - if (MachOFlags & macho::STF_StabsEntryMask) - Result |= SymbolRef::SF_FormatSpecific; - - if (MachOType & MachO::NlistMaskExternal) { - Result |= SymbolRef::SF_Global; - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Common; - } - - if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) - Result |= SymbolRef::SF_Weak; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) - Result |= SymbolRef::SF_Absolute; - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t index = Entry->SectionIndex; - - if (index == 0) - Res = end_sections(); - else - Res = section_iterator(SectionRef(Sections[index-1], this)); - - return object_error::success; -} - -error_code MachOObjectFileBase::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t n_type = Entry->Type; - - Res = SymbolRef::ST_Other; - - // If this is a STAB debugging symbol, we can do nothing more. - if (n_type & MachO::NlistMaskStab) { - Res = SymbolRef::ST_Debug; - return object_error::success; - } - - switch (n_type & MachO::NlistMaskType) { - case MachO::NListTypeUndefined : - Res = SymbolRef::ST_Unknown; - break; - case MachO::NListTypeSection : - Res = SymbolRef::ST_Function; - break; - } - return object_error::success; -} - error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, uint64_t &Val) const { report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); } -symbol_iterator MachOObjectFileBase::begin_symbols() const { - // DRI.d.a = segment number; DRI.d.b = symbol index. - DataRefImpl DRI; - moveToNextSymbol(DRI); - return symbol_iterator(SymbolRef(DRI, this)); -} - -symbol_iterator MachOObjectFileBase::end_symbols() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return symbol_iterator(SymbolRef(DRI, this)); -} - symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { // TODO: implement report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); @@ -347,23 +120,7 @@ std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { return std::distance(Sections.begin(), loc); } -const MachOObjectFileBase::SectionBase* -MachOObjectFileBase::getSectionBase(DataRefImpl DRI) const { - const LoadCommand *Command = getLoadCommandInfo(DRI.d.a); - uintptr_t CommandAddr = reinterpret_cast(Command); - - bool Is64 = is64Bit(); - unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFile64Le::SegmentLoadCommand) : - sizeof(MachOObjectFile32Le::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFile64Le::Section) : - sizeof(MachOObjectFile32Le::Section); - - uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast(SectionAddr); -} - -static StringRef parseSegmentOrSectionName(const char *P) { +StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const { if (P[15] == 0) // Null terminated. return P; @@ -371,30 +128,6 @@ static StringRef parseSegmentOrSectionName(const char *P) { return StringRef(P, 16); } -ArrayRef MachOObjectFileBase::getSectionRawName(DataRefImpl DRI) const { - const SectionBase *Base = getSectionBase(DRI); - return ArrayRef(Base->Name); -} - -error_code MachOObjectFileBase::getSectionName(DataRefImpl DRI, - StringRef &Result) const { - ArrayRef Raw = getSectionRawName(DRI); - Result = parseSegmentOrSectionName(Raw.data()); - return object_error::success; -} - -ArrayRef -MachOObjectFileBase::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef(Base->SegmentName); -} - -StringRef -MachOObjectFileBase::getSectionFinalSegmentName(DataRefImpl DRI) const { - ArrayRef Raw = getSectionRawFinalSegmentName(DRI); - return parseSegmentOrSectionName(Raw.data()); -} - error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. @@ -441,11 +174,6 @@ relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) con return relocation_iterator(RelocationRef(ret, this)); } -section_iterator MachOObjectFileBase::end_sections() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return section_iterator(SectionRef(DRI, this)); -} /*===-- Relocations -------------------------------------------------------===*/ @@ -456,88 +184,6 @@ error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, return object_error::success; } -// Helper to advance a section or symbol iterator multiple increments at a time. -template -error_code advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template -void advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); -} - -void -MachOObjectFileBase::printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const { - // Target of a scattered relocation is an address. In the interest of - // generating pretty output, scan through the symbol table looking for a - // symbol that aligns with that address. If we find one, print it. - // Otherwise, we just print the hex address of the target. - if (isScattered(RE)) { - uint32_t Val = RE->SymbolNum; - - error_code ec; - for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = RE->getExternal(); - uint32_t Val = RE->Address; - - if (isExtern) { - symbol_iterator SI = begin_symbols(); - advanceTo(SI, Val); - SI->getName(S); - } else { - section_iterator SI = begin_sections(); - advanceTo(SI, Val); - SI->getName(S); - } - - fmt << S; -} - error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); @@ -561,53 +207,5 @@ uint8_t MachOObjectFileBase::getBytesInAddress() const { return is64Bit() ? 8 : 4; } -StringRef MachOObjectFileBase::getFileFormatName() const { - if (!is64Bit()) { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return "Mach-O 32-bit i386"; - case llvm::MachO::CPUTypeARM: - return "Mach-O arm"; - case llvm::MachO::CPUTypePowerPC: - return "Mach-O 32-bit ppc"; - default: - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) == 0 && - "64-bit object file when we're not 64-bit?"); - return "Mach-O 32-bit unknown"; - } - } - - // Make sure the cpu type has the correct mask. - assert((getHeader()->CPUType & llvm::MachO::CPUArchABI64) - == llvm::MachO::CPUArchABI64 && - "32-bit object file when we're 64-bit?"); - - switch (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: - return "Mach-O 64-bit unknown"; - } -} - -unsigned MachOObjectFileBase::getArch() const { - switch (getHeader()->CPUType) { - case llvm::MachO::CPUTypeI386: - return Triple::x86; - case llvm::MachO::CPUTypeX86_64: - return Triple::x86_64; - case llvm::MachO::CPUTypeARM: - return Triple::arm; - case llvm::MachO::CPUTypePowerPC: - return Triple::ppc; - case llvm::MachO::CPUTypePowerPC64: - return Triple::ppc64; - default: - return Triple::UnknownArch; - } -} - } // end namespace object } // end namespace llvm diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc new file mode 100644 index 0000000000..dd2e956499 Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc differ diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 new file mode 100644 index 0000000000..20ec8ef23f Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-ppc64 differ diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index 96aac231db..6dc08eeb06 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Relocations [ COFF-NEXT: Section (1) .text { @@ -40,3 +44,41 @@ MACHO-X86-64-NEXT: 0x9 1 2 1 X86_64_RELOC_BRANCH 0 _puts MACHO-X86-64-NEXT: 0x4 1 2 1 X86_64_RELOC_SIGNED 0 L_.str MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Relocations [ +MACHO-PPC-NEXT: Section __text { +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section __picsymbolstub1 { +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section __la_symbol_ptr { +MACHO-PPC-NEXT: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + +MACHO-PPC64: Relocations [ +MACHO-PPC64-NEXT: Section __text { +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section __picsymbolstub1 { +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section __la_symbol_ptr { +MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index a12d9e4646..3e42ab94fe 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Sections [ COFF-NEXT: Section { @@ -249,3 +253,312 @@ MACHO-X86-64-NEXT: 0000: 48656C6C 6F20576F 726C640A 00 |Hello World. MACHO-X86-64-NEXT: ) MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Sections [ +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 0 +MACHO-PPC-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x0 +MACHO-PPC-NEXT: Size: 0x3C +MACHO-PPC-NEXT: Offset: 528 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x27C +MACHO-PPC-NEXT: RelocationCount: 5 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: Symbol { +MACHO-PPC-NEXT: Name: _f (4) +MACHO-PPC-NEXT: Type: 0xF +MACHO-PPC-NEXT: Section: __text (0x1) +MACHO-PPC-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC-NEXT: Flags [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Value: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 7C0802A6 93E1FFFC 429F0005 7FE802A6 ||.......B.......| +MACHO-PPC-NEXT: 0010: 90010008 9421FFB0 48000029 3C5F0000 |.....!..H..)<_..| +MACHO-PPC-NEXT: 0020: 38210050 80420058 80010008 83E1FFFC |8!.P.B.X........| +MACHO-PPC-NEXT: 0030: 7C0803A6 80620000 4E800020 ||....b..N.. | +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 1 +MACHO-PPC-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x40 +MACHO-PPC-NEXT: Size: 0x20 +MACHO-PPC-NEXT: Offset: 592 +MACHO-PPC-NEXT: Alignment: 5 +MACHO-PPC-NEXT: RelocationOffset: 0x2A4 +MACHO-PPC-NEXT: RelocationCount: 4 +MACHO-PPC-NEXT: Type: 0x8 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x20 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 7C0802A6 429F0005 7D6802A6 3D6B0000 ||...B...}h..=k..| +MACHO-PPC-NEXT: 0010: 7C0803A6 858B0020 7D8903A6 4E800420 ||...... }...N.. | +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 2 +MACHO-PPC-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x60 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 624 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: Symbol { +MACHO-PPC-NEXT: Name: _b (1) +MACHO-PPC-NEXT: Type: 0xF +MACHO-PPC-NEXT: Section: __data (0x3) +MACHO-PPC-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC-NEXT: Flags [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Value: 0x60 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 0000002A |...*| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 3 +MACHO-PPC-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x64 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 628 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x6 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x1 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 00000000 |....| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 4 +MACHO-PPC-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x68 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 632 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x2C4 +MACHO-PPC-NEXT: RelocationCount: 1 +MACHO-PPC-NEXT: Type: 0x7 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x2 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: Relocations [ +MACHO-PPC-NEXT: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Symbols [ +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: SectionData ( +MACHO-PPC-NEXT: 0000: 00000000 |....| +MACHO-PPC-NEXT: ) +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + + +MACHO-PPC64: Sections [ +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 0 +MACHO-PPC64-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x0 +MACHO-PPC64-NEXT: Size: 0x3C +MACHO-PPC64-NEXT: Offset: 608 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x2D4 +MACHO-PPC64-NEXT: RelocationCount: 5 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: Symbol { +MACHO-PPC64-NEXT: Name: _f (4) +MACHO-PPC64-NEXT: Type: 0xF +MACHO-PPC64-NEXT: Section: __text (0x1) +MACHO-PPC64-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC64-NEXT: Flags [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Value: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 7C0802A6 FBE1FFF8 429F0005 7FE802A6 ||.......B.......| +MACHO-PPC64-NEXT: 0010: F8010010 F821FF81 48000029 3C5F0000 |.....!..H..)<_..| +MACHO-PPC64-NEXT: 0020: 38210080 E8420058 E8010010 EBE1FFF8 |8!...B.X........| +MACHO-PPC64-NEXT: 0030: 7C0803A6 E8620002 4E800020 ||....b..N.. | +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 1 +MACHO-PPC64-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x40 +MACHO-PPC64-NEXT: Size: 0x20 +MACHO-PPC64-NEXT: Offset: 672 +MACHO-PPC64-NEXT: Alignment: 5 +MACHO-PPC64-NEXT: RelocationOffset: 0x2FC +MACHO-PPC64-NEXT: RelocationCount: 4 +MACHO-PPC64-NEXT: Type: 0x8 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x20 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 7C0802A6 429F0005 7D6802A6 3D6B0000 ||...B...}h..=k..| +MACHO-PPC64-NEXT: 0010: 7C0803A6 E98B0025 7D8903A6 4E800420 ||......%}...N.. | +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 2 +MACHO-PPC64-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x60 +MACHO-PPC64-NEXT: Size: 0x4 +MACHO-PPC64-NEXT: Offset: 704 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: Symbol { +MACHO-PPC64-NEXT: Name: _b (1) +MACHO-PPC64-NEXT: Type: 0xF +MACHO-PPC64-NEXT: Section: __data (0x3) +MACHO-PPC64-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-PPC64-NEXT: Flags [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Value: 0x60 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 0000002A |...*| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 3 +MACHO-PPC64-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x64 +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 708 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x6 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x1 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 00000000 00000000 |........| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 4 +MACHO-PPC64-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x6C +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 716 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x31C +MACHO-PPC64-NEXT: RelocationCount: 1 +MACHO-PPC64-NEXT: Type: 0x7 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x2 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: Relocations [ +MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Symbols [ +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: SectionData ( +MACHO-PPC64-NEXT: 0000: 00000000 00000000 |........| +MACHO-PPC64-NEXT: ) +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/test/tools/llvm-readobj/sections.test b/test/tools/llvm-readobj/sections.test index f4da9e3c39..b569682497 100644 --- a/test/tools/llvm-readobj/sections.test +++ b/test/tools/llvm-readobj/sections.test @@ -6,6 +6,10 @@ RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-i386 \ RUN: | FileCheck %s -check-prefix MACHO-I386 RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-x86-64 \ RUN: | FileCheck %s -check-prefix MACHO-X86-64 +RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc \ +RUN: | FileCheck %s -check-prefix MACHO-PPC +RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc64 \ +RUN: | FileCheck %s -check-prefix MACHO-PPC64 COFF: Sections [ COFF-NEXT: Section { @@ -151,3 +155,177 @@ MACHO-X86-64-NEXT: Reserved1: 0x0 MACHO-X86-64-NEXT: Reserved2: 0x0 MACHO-X86-64-NEXT: } MACHO-X86-64-NEXT:] + +MACHO-PPC: Sections [ +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 0 +MACHO-PPC-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x0 +MACHO-PPC-NEXT: Size: 0x3C +MACHO-PPC-NEXT: Offset: 528 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x27C +MACHO-PPC-NEXT: RelocationCount: 5 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 1 +MACHO-PPC-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x40 +MACHO-PPC-NEXT: Size: 0x20 +MACHO-PPC-NEXT: Offset: 592 +MACHO-PPC-NEXT: Alignment: 5 +MACHO-PPC-NEXT: RelocationOffset: 0x2A4 +MACHO-PPC-NEXT: RelocationCount: 4 +MACHO-PPC-NEXT: Type: 0x8 +MACHO-PPC-NEXT: Attributes [ (0x800004) +MACHO-PPC-NEXT: PureInstructions (0x800000) +MACHO-PPC-NEXT: SomeInstructions (0x4) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x20 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 2 +MACHO-PPC-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x60 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 624 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x0 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x0 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 3 +MACHO-PPC-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x64 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 628 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x0 +MACHO-PPC-NEXT: RelocationCount: 0 +MACHO-PPC-NEXT: Type: 0x6 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x1 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: Section { +MACHO-PPC-NEXT: Index: 4 +MACHO-PPC-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC-NEXT: Address: 0x68 +MACHO-PPC-NEXT: Size: 0x4 +MACHO-PPC-NEXT: Offset: 632 +MACHO-PPC-NEXT: Alignment: 2 +MACHO-PPC-NEXT: RelocationOffset: 0x2C4 +MACHO-PPC-NEXT: RelocationCount: 1 +MACHO-PPC-NEXT: Type: 0x7 +MACHO-PPC-NEXT: Attributes [ (0x0) +MACHO-PPC-NEXT: ] +MACHO-PPC-NEXT: Reserved1: 0x2 +MACHO-PPC-NEXT: Reserved2: 0x0 +MACHO-PPC-NEXT: } +MACHO-PPC-NEXT: ] + +MACHO-PPC64: Sections [ +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 0 +MACHO-PPC64-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x0 +MACHO-PPC64-NEXT: Size: 0x3C +MACHO-PPC64-NEXT: Offset: 608 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x2D4 +MACHO-PPC64-NEXT: RelocationCount: 5 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 1 +MACHO-PPC64-NEXT: Name: __picsymbolstub1 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 31) +MACHO-PPC64-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x40 +MACHO-PPC64-NEXT: Size: 0x20 +MACHO-PPC64-NEXT: Offset: 672 +MACHO-PPC64-NEXT: Alignment: 5 +MACHO-PPC64-NEXT: RelocationOffset: 0x2FC +MACHO-PPC64-NEXT: RelocationCount: 4 +MACHO-PPC64-NEXT: Type: 0x8 +MACHO-PPC64-NEXT: Attributes [ (0x800004) +MACHO-PPC64-NEXT: PureInstructions (0x800000) +MACHO-PPC64-NEXT: SomeInstructions (0x4) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x20 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 2 +MACHO-PPC64-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x60 +MACHO-PPC64-NEXT: Size: 0x4 +MACHO-PPC64-NEXT: Offset: 704 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x0 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x0 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 3 +MACHO-PPC64-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x64 +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 708 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x0 +MACHO-PPC64-NEXT: RelocationCount: 0 +MACHO-PPC64-NEXT: Type: 0x6 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x1 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: Section { +MACHO-PPC64-NEXT: Index: 4 +MACHO-PPC64-NEXT: Name: __la_symbol_ptr (5F 5F 6C 61 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-PPC64-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-PPC64-NEXT: Address: 0x6C +MACHO-PPC64-NEXT: Size: 0x8 +MACHO-PPC64-NEXT: Offset: 716 +MACHO-PPC64-NEXT: Alignment: 2 +MACHO-PPC64-NEXT: RelocationOffset: 0x31C +MACHO-PPC64-NEXT: RelocationCount: 1 +MACHO-PPC64-NEXT: Type: 0x7 +MACHO-PPC64-NEXT: Attributes [ (0x0) +MACHO-PPC64-NEXT: ] +MACHO-PPC64-NEXT: Reserved1: 0x2 +MACHO-PPC64-NEXT: Reserved2: 0x0 +MACHO-PPC64-NEXT: } +MACHO-PPC64-NEXT: ] diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 89847d0499..4b6cb5f54c 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -27,6 +27,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/MachO.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" @@ -183,11 +184,14 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -static void getSectionsAndSymbols(const MachOObjectFileBase::Header *Header, - MachOObjectFileBase *MachOObj, - std::vector &Sections, - std::vector &Symbols, - SmallVectorImpl &FoundFns) { +template +static void +getSectionsAndSymbols(const typename MachOObjectFileMiddle::Header *Header, + const MachOObjectFileMiddle *MachOObj, + std::vector &Sections, + std::vector &Symbols, + SmallVectorImpl &FoundFns) { + typedef MachOObjectFileMiddle ObjType; error_code ec; for (symbol_iterator SI = MachOObj->begin_symbols(), SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) @@ -202,19 +206,23 @@ static void getSectionsAndSymbols(const MachOObjectFileBase::Header *Header, } for (unsigned i = 0; i != Header->NumLoadCommands; ++i) { - const MachOObjectFileBase::LoadCommand *Command = + const typename ObjType::LoadCommand *Command = MachOObj->getLoadCommandInfo(i); if (Command->Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - const MachOObjectFileBase::LinkeditDataLoadCommand *LLC = - reinterpret_cast(Command); + const typename ObjType::LinkeditDataLoadCommand *LLC = + reinterpret_cast(Command); MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); } } } +template +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFileMiddle *MachOOF); + void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr Buff; @@ -226,7 +234,18 @@ void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr MachOOF(static_cast( ObjectFile::createMachOObjectFile(Buff.take()))); - const Target *TheTarget = GetTarget(MachOOF.get()); + if (MachOObjectFileLE *O = dyn_cast(MachOOF.get())) { + DisassembleInputMachO2(Filename, O); + return; + } + MachOObjectFileBE *O = cast(MachOOF.get()); + DisassembleInputMachO2(Filename, O); +} + +template +static void DisassembleInputMachO2(StringRef Filename, + MachOObjectFileMiddle *MachOOF) { + const Target *TheTarget = GetTarget(MachOOF); if (!TheTarget) { // GetTarget prints out stuff. return; @@ -254,13 +273,14 @@ void llvm::DisassembleInputMachO(StringRef Filename) { outs() << '\n' << Filename << ":\n\n"; - const MachOObjectFileBase::Header *Header = MachOOF->getHeader(); + const typename MachOObjectFileMiddle::Header *Header = + MachOOF->getHeader(); std::vector Sections; std::vector Symbols; SmallVector FoundFns; - getSectionsAndSymbols(Header, MachOOF.get(), Sections, Symbols, FoundFns); + getSectionsAndSymbols(Header, MachOOF, Sections, Symbols, FoundFns); // Make a copy of the unsorted symbol list. FIXME: duplication std::vector UnsortedSymbols(Symbols); @@ -274,7 +294,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { #endif OwningPtr diContext; - ObjectFile *DbgObj = MachOOF.get(); + ObjectFile *DbgObj = MachOOF; // Try to find debug info and set up the DIContext for it. if (UseDbg) { // A separate DSym file path was specified, parse it as a macho file, @@ -563,7 +583,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Relocs[j].second.getName(SymName); outs() << "\t# " << SymName << ' '; - DumpAddress(Addr, Sections, MachOOF.get(), outs()); + DumpAddress(Addr, Sections, MachOOF, outs()); } // If this instructions contains an address, see if we can evaluate @@ -572,7 +592,7 @@ void llvm::DisassembleInputMachO(StringRef Filename) { Inst.Address, Inst.Size); if (targ != -1ULL) - DumpAddress(targ, Sections, MachOOF.get(), outs()); + DumpAddress(targ, Sections, MachOOF, outs()); // Print debug info. if (diContext) { diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 4790d7a5fe..5a0519ddc1 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -191,6 +191,14 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { return a_addr < b_addr; } +StringRef +getSectionFinalSegmentName(const MachOObjectFileBase *MachO, DataRefImpl DR) { + if (const MachOObjectFileLE *O = dyn_cast(MachO)) + return O->getSectionFinalSegmentName(DR); + const MachOObjectFileBE *O = dyn_cast(MachO); + return O->getSectionFinalSegmentName(DR); +} + static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); // getTarget() will have already issued a diagnostic if necessary, so @@ -255,9 +263,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFileBase *MachO = dyn_cast(Obj)) { + if (const MachOObjectFileBase *MachO = + dyn_cast(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); - SegmentName = MachO->getSectionFinalSegmentName(DR); + SegmentName = getSectionFinalSegmentName(MachO, DR); } StringRef name; if (error(i->getName(name))) break; @@ -591,9 +600,10 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFileBase *MachO = dyn_cast(o)) { + if (const MachOObjectFileBase *MachO = + dyn_cast(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); - StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); + StringRef SegmentName = getSectionFinalSegmentName(MachO, DR); outs() << SegmentName << ","; } StringRef SectionName; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 69f1d63b12..d207eabb52 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const llvm::object::MachOObjectFileBase *Obj, StreamWriter& Writer) + MachODumper(const MachOObjectFileBase *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,7 +43,14 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - const llvm::object::MachOObjectFileBase *Obj; + template + void printRelocation(const MachOObjectFileMiddle *Obj, + section_iterator SecI, relocation_iterator RelI); + + template + void printSections(const MachOObjectFileMiddle *Obj); + + const MachOObjectFileBase *Obj; }; } // namespace @@ -157,58 +164,59 @@ namespace { }; } +template +static void getSection(const MachOObjectFile *Obj, + DataRefImpl DRI, + MachOSection &Section) { + const typename MachOObjectFile::Section *Sect = Obj->getSection(DRI); + Section.Address = Sect->Address; + Section.Size = Sect->Size; + Section.Offset = Sect->Offset; + Section.Alignment = Sect->Align; + Section.RelocationTableOffset = Sect->RelocationTableOffset; + Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; + Section.Flags = Sect->Flags; + Section.Reserved1 = Sect->Reserved1; + Section.Reserved2 = Sect->Reserved2; +} + static void getSection(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSection &Section) { - if (const MachOObjectFile64Le *O = dyn_cast(Obj)) { - const MachOObjectFile64Le::Section *Sect = O->getSection(DRI); - - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; - } else { - const MachOObjectFile32Le *O2 = cast(Obj); - const MachOObjectFile32Le::Section *Sect = O2->getSection(DRI); - - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; - } + if (const MachOObjectFileLE32 *O = dyn_cast(Obj)) + return getSection(O, DRI, Section); + if (const MachOObjectFileLE64 *O = dyn_cast(Obj)) + return getSection(O, DRI, Section); + if (const MachOObjectFileBE32 *O = dyn_cast(Obj)) + return getSection(O, DRI, Section); + const MachOObjectFileBE64 *O = cast(Obj); + getSection(O, DRI, Section); +} + +template +static void getSymbol(const MachOObjectFile *Obj, + DataRefImpl DRI, + MachOSymbol &Symbol) { + const typename MachOObjectFile::SymbolTableEntry *Entry = + Obj->getSymbolTableEntry(DRI); + Symbol.StringIndex = Entry->StringIndex; + Symbol.Type = Entry->Type; + Symbol.SectionIndex = Entry->SectionIndex; + Symbol.Flags = Entry->Flags; + Symbol.Value = Entry->Value; } static void getSymbol(const MachOObjectFileBase *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (const MachOObjectFile64Le *O = dyn_cast(Obj)) { - const MachOObjectFile64Le::SymbolTableEntry *Entry = - O->getSymbolTableEntry(DRI); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; - } else { - const MachOObjectFile32Le *O2 = cast(Obj); - const MachOObjectFile32Le::SymbolTableEntry *Entry = - O2->getSymbolTableEntry(DRI); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; - } + if (const MachOObjectFileLE32 *O = dyn_cast(Obj)) + return getSymbol(O, DRI, Symbol); + if (const MachOObjectFileLE64 *O = dyn_cast(Obj)) + return getSymbol(O, DRI, Symbol); + if (const MachOObjectFileBE32 *O = dyn_cast(Obj)) + return getSymbol(O, DRI, Symbol); + const MachOObjectFileBE64 *O = cast(Obj); + getSymbol(O, DRI, Symbol); } void MachODumper::printFileHeaders() { @@ -216,6 +224,14 @@ void MachODumper::printFileHeaders() { } void MachODumper::printSections() { + if (const MachOObjectFileLE *O = dyn_cast(Obj)) + return printSections(O); + const MachOObjectFileBE *O = cast(Obj); + return printSections(O); +} + +template +void MachODumper::printSections(const MachOObjectFileMiddle *Obj) { ListScope Group(W, "Sections"); int SectionIndex = -1; @@ -328,6 +344,16 @@ void MachODumper::printRelocations() { void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { + if (const MachOObjectFileLE *O = dyn_cast(Obj)) + return printRelocation(O, SecI, RelI); + const MachOObjectFileBE *O = cast(Obj); + return printRelocation(O, SecI, RelI); +} + +template +void MachODumper::printRelocation(const MachOObjectFileMiddle *Obj, + section_iterator SecI, + relocation_iterator RelI) { uint64_t Offset; SmallString<32> RelocName; StringRef SymbolName; @@ -338,14 +364,15 @@ void MachODumper::printRelocation(section_iterator SecI, if (error(Symbol.getName(SymbolName))) return; DataRefImpl DR = RelI->getRawDataRefImpl(); - const MachOObjectFileBase::RelocationEntry *RE = Obj->getRelocation(DR); - bool IsScattered = Obj->isScattered(RE); + const typename MachOObjectFileMiddle::RelocationEntry *RE = + Obj->getRelocation(DR); + bool IsScattered = Obj->isRelocationScattered(RE); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); - W.printNumber("PCRel", Obj->isPCRel(RE)); - W.printNumber("Length", Obj->getLength(RE)); + W.printNumber("PCRel", Obj->isRelocationPCRel(RE)); + W.printNumber("Length", Obj->getRelocationLength(RE)); if (IsScattered) W.printString("Extern", StringRef("N/A")); else @@ -356,8 +383,8 @@ void MachODumper::printRelocation(section_iterator SecI, } else { raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << Obj->isPCRel(RE) - << " " << Obj->getLength(RE); + << " " << Obj->isRelocationPCRel(RE) + << " " << Obj->getRelocationLength(RE); if (IsScattered) OS << " n/a"; else @@ -399,6 +426,7 @@ void MachODumper::printSymbol(symbol_iterator SymI) { StringRef SectionName; section_iterator SecI(Obj->end_sections()); if (error(SymI->getSection(SecI)) || + SecI == Obj->end_sections() || error(SecI->getName(SectionName))) SectionName = ""; -- cgit v1.2.3-70-g09d2 From fd7aa38e304a09fa0ef51b85b773b649b7e58c5e Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 18 Apr 2013 18:08:55 +0000 Subject: At Jim Grosbach's request detemplate Object/MachO.h. We are still able to handle mixed endian objects by swapping one struct at a time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179778 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/Binary.h | 3 +- include/llvm/Object/MachO.h | 1645 ++------------------ lib/Object/MachOObjectFile.cpp | 1461 ++++++++++++++++- .../llvm-readobj/Inputs/trivial.obj.macho-arm | Bin 0 -> 908 bytes test/tools/llvm-readobj/relocations.test | 89 ++ test/tools/llvm-readobj/sections-ext.test | 277 ++++ test/tools/llvm-readobj/sections.test | 121 ++ tools/llvm-objdump/MachODump.cpp | 43 +- tools/llvm-objdump/llvm-objdump.cpp | 20 +- tools/llvm-readobj/MachODumper.cpp | 133 +- tools/llvm-symbolizer/LLVMSymbolize.cpp | 2 +- 11 files changed, 2039 insertions(+), 1755 deletions(-) create mode 100644 test/tools/llvm-readobj/Inputs/trivial.obj.macho-arm (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index ac5bfed4bf..78fcf6feb8 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -100,7 +100,8 @@ public: } bool isLittleEndian() const { - return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B); + return !(TypeID == ID_ELF32B || TypeID == ID_ELF64B || + TypeID == ID_MachO32B || TypeID == ID_MachO64B); } }; diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 8867068985..cec649e4b1 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// // -// This file declares the MachOObjectFile class, which binds the MachOObject -// class to the generic ObjectFile wrapper. +// This file declares the MachOObjectFile class, which implement the ObjectFile +// interface for MachO files. // //===----------------------------------------------------------------------===// @@ -17,1607 +17,140 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Format.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { namespace object { -using support::endianness; - -template -struct MachOType { - static const endianness TargetEndianness = E; - static const bool Is64Bits = B; -}; - -template -struct MachOInt24Impl; - -template<> -struct MachOInt24Impl { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; - } -}; - -template<> -struct MachOInt24Impl { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[0] << 24) | (bytes[1] << 16) | bytes[2]; - } -}; - -template -struct MachODataTypeTypedefHelperCommon { - typedef support::detail::packed_endian_specific_integral - MachOInt16; - typedef support::detail::packed_endian_specific_integral - MachOInt32; - typedef support::detail::packed_endian_specific_integral - MachOInt64; - typedef MachOInt24Impl MachOInt24; -}; - -#define LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \ -typedef typename MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24; - -#define LLVM_MACHOB_IMPORT_TYPES(E) \ -typedef MachODataTypeTypedefHelperCommon::MachOInt16 MachOInt16; \ -typedef MachODataTypeTypedefHelperCommon::MachOInt32 MachOInt32; \ -typedef MachODataTypeTypedefHelperCommon::MachOInt64 MachOInt64; \ -typedef MachODataTypeTypedefHelperCommon::MachOInt24 MachOInt24; - -template -struct MachODataTypeTypedefHelper; - -template -struct MachODataTypeTypedefHelper > { - typedef MachODataTypeTypedefHelperCommon Base; - typedef typename Base::MachOInt32 MachOIntPtr; -}; - -template -struct MachODataTypeTypedefHelper > { - typedef MachODataTypeTypedefHelperCommon Base; - typedef typename Base::MachOInt64 MachOIntPtr; -}; - -#define LLVM_MACHO_IMPORT_TYPES(MachOT, E, B) \ -LLVM_MACHOB_IMPORT_TYPES_TYPENAME(E) \ -typedef typename \ - MachODataTypeTypedefHelper >::MachOIntPtr MachOIntPtr; - -namespace MachOFormat { - struct SectionBase { - char Name[16]; - char SegmentName[16]; - }; - - template - struct Section; - - template - struct Section > { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - char Name[16]; - char SegmentName[16]; - MachOInt32 Address; - MachOInt32 Size; - MachOInt32 Offset; - MachOInt32 Align; - MachOInt32 RelocationTableOffset; - MachOInt32 NumRelocationTableEntries; - MachOInt32 Flags; - MachOInt32 Reserved1; - MachOInt32 Reserved2; - }; - - template - struct Section > { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - char Name[16]; - char SegmentName[16]; - MachOInt64 Address; - MachOInt64 Size; - MachOInt32 Offset; - MachOInt32 Align; - MachOInt32 RelocationTableOffset; - MachOInt32 NumRelocationTableEntries; - MachOInt32 Flags; - MachOInt32 Reserved1; - MachOInt32 Reserved2; - MachOInt32 Reserved3; - }; - - struct MachOInt24 { - uint8_t bytes[3]; - operator uint32_t() const { - return (bytes[2] << 24) | (bytes[1] << 16) | bytes[0]; - } - }; - - template - struct RelocationEntry; - - template<> - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned External : 1; - unsigned Type : 4; - }; - - template<> - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned Type : 4; - unsigned External : 1; - unsigned Length : 2; - unsigned PCRel : 1; - }; - - template<> - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::big) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned Type : 4; - unsigned External : 1; - unsigned Length : 2; - unsigned PCRel : 1; - }; - - template<> - struct RelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::big) - MachOInt32 Address; - MachOInt24 SymbolNum; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned External : 1; - unsigned Type : 4; - }; - - template - struct ScatteredRelocationEntry; - - template<> - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt24 Address; - unsigned Type : 4; - unsigned Length : 2; - unsigned PCRel : 1; - unsigned Scattered : 1; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::little) - MachOInt24 Address; - unsigned Scattered : 1; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned Type : 4; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::big) - unsigned Type : 4; - unsigned Length : 2; - unsigned PCRel : 1; - unsigned Scattered : 1; - MachOInt24 Address; - MachOInt32 Value; - }; - - template<> - struct ScatteredRelocationEntry { - LLVM_MACHOB_IMPORT_TYPES(support::big) - unsigned Scattered : 1; - unsigned PCRel : 1; - unsigned Length : 2; - unsigned Type : 4; - MachOInt24 Address; - MachOInt32 Value; - }; - - template - struct SymbolTableEntryBase { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 StringIndex; - uint8_t Type; - uint8_t SectionIndex; - MachOInt16 Flags; - }; - - template - struct SymbolTableEntry; - - template - struct SymbolTableEntry > { - LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) - MachOInt32 StringIndex; - uint8_t Type; - uint8_t SectionIndex; - MachOInt16 Flags; - MachOIntPtr Value; - }; - - template - struct LoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - }; - - template - struct SymtabLoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - MachOInt32 SymbolTableOffset; - MachOInt32 NumSymbolTableEntries; - MachOInt32 StringTableOffset; - MachOInt32 StringTableSize; - }; - - template - struct SegmentLoadCommand; - - template - struct SegmentLoadCommand > { - LLVM_MACHO_IMPORT_TYPES(MachOType, TargetEndianness, Is64Bits) - MachOInt32 Type; - MachOInt32 Size; - char Name[16]; - MachOIntPtr VMAddress; - MachOIntPtr VMSize; - MachOIntPtr FileOffset; - MachOIntPtr FileSize; - MachOInt32 MaxVMProtection; - MachOInt32 InitialVMProtection; - MachOInt32 NumSections; - MachOInt32 Flags; - }; - - template - struct LinkeditDataLoadCommand { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Type; - MachOInt32 Size; - MachOInt32 DataOffset; - MachOInt32 DataSize; - }; - - template - struct Header { - LLVM_MACHOB_IMPORT_TYPES_TYPENAME(TargetEndianness) - MachOInt32 Magic; - MachOInt32 CPUType; - MachOInt32 CPUSubtype; - MachOInt32 FileType; - MachOInt32 NumLoadCommands; - MachOInt32 SizeOfLoadCommands; - MachOInt32 Flags; - }; -} - -class MachOObjectFileBase : public ObjectFile { -public: - typedef MachOFormat::SectionBase SectionBase; - - MachOObjectFileBase(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, - error_code &ec); - - virtual symbol_iterator begin_dynamic_symbols() const; - virtual symbol_iterator end_dynamic_symbols() const; - virtual library_iterator begin_libraries_needed() const; - virtual library_iterator end_libraries_needed() const; - - virtual uint8_t getBytesInAddress() const; - virtual StringRef getLoadName() const; - - bool is64Bit() const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - unsigned getHeaderSize() const; - StringRef getData(size_t Offset, size_t Size) const; - - static inline bool classof(const Binary *v) { - return v->isMachO(); - } - -protected: - StringRef parseSegmentOrSectionName(const char *P) const; - - virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; - virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const; - virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; - virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; - virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; - - virtual error_code getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const; - - virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; - virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; - virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const; - - std::size_t getSectionIndex(DataRefImpl Sec) const; - - typedef SmallVector SectionList; - SectionList Sections; -}; - -template -class MachOObjectFileMiddle : public MachOObjectFileBase { +class MachOObjectFile : public ObjectFile { public: + struct LoadCommandInfo { + const char *Ptr; // Where in memory the load command is. + macho::LoadCommand C; // The command itself. + }; - typedef MachOFormat::SymbolTableEntryBase - SymbolTableEntryBase; - typedef MachOFormat::LinkeditDataLoadCommand - LinkeditDataLoadCommand; - typedef MachOFormat::Header Header; - typedef MachOFormat::SymtabLoadCommand SymtabLoadCommand; - typedef MachOFormat::RelocationEntry RelocationEntry; - typedef MachOFormat::ScatteredRelocationEntry - ScatteredRelocationEntry; - typedef MachOFormat::LoadCommand LoadCommand; - - MachOObjectFileMiddle(MemoryBuffer *Object, bool Is64Bits, error_code &ec); - - const Header *getHeader() const; - const LoadCommand *getLoadCommandInfo(unsigned Index) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; - bool isRelocationScattered(const RelocationEntry *RE) const; - bool isRelocationPCRel(const RelocationEntry *RE) const; - unsigned getRelocationLength(const RelocationEntry *RE) const; - unsigned getRelocationTypeImpl(const RelocationEntry *RE) const; - - void moveToNextSymbol(DataRefImpl &DRI) const; - void printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const; - const SectionBase *getSectionBase(DataRefImpl DRI) const; - const SymbolTableEntryBase *getSymbolTableEntryBase(DataRefImpl DRI) const; - unsigned getCPUType() const; - - // In a MachO file, sections have a segment name. This is used in the .o - // files. They have a single segment, but this field specifies which segment - // a section should be put in in the final object. - StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - - // Names are stored as 16 bytes. These returns the raw 16 bytes without - // interpreting them as a C string. - ArrayRef getSectionRawName(DataRefImpl Sec) const; - ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; + MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64Bits, + error_code &ec); - virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; - virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; + virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; - virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; + virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; + virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const; - virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; - virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const; - virtual symbol_iterator begin_symbols() const; - virtual unsigned getArch() const; - virtual StringRef getFileFormatName() const; - virtual symbol_iterator end_symbols() const; - virtual section_iterator end_sections() const; - - static bool classof(const Binary *v); - -private: - // Helper to advance a section or symbol iterator multiple increments at a - // time. - template - static error_code advance(T &it, size_t Val); - - template - static void advanceTo(T &it, size_t Val); -}; - -template -struct MachOObjectFileHelperCommon; - -template -struct MachOObjectFileHelperCommon > { - typedef - MachOFormat::SegmentLoadCommand > - SegmentLoadCommand; - typedef MachOFormat::SymbolTableEntry > - SymbolTableEntry; - typedef MachOFormat::Section > Section; -}; - -template -struct MachOObjectFileHelper; - -template -struct MachOObjectFileHelper > : - public MachOObjectFileHelperCommon > { - static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment; -}; - -template -struct MachOObjectFileHelper > : - public MachOObjectFileHelperCommon > { - static const macho::LoadCommandType SegmentLoadType = macho::LCT_Segment64; -}; - -template -class MachOObjectFile : public MachOObjectFileMiddle { -public: - static const endianness TargetEndianness = MachOT::TargetEndianness; - static const bool Is64Bits = MachOT::Is64Bits; - - typedef MachOObjectFileMiddle Base; - typedef typename Base::RelocationEntry RelocationEntry; - typedef typename Base::SectionBase SectionBase; - typedef typename Base::SymbolTableEntryBase SymbolTableEntryBase; - typedef typename Base::LoadCommand LoadCommand; - - typedef MachOObjectFileHelper Helper; - static const macho::LoadCommandType SegmentLoadType = Helper::SegmentLoadType; - typedef typename Helper::SegmentLoadCommand SegmentLoadCommand; - typedef typename Helper::SymbolTableEntry SymbolTableEntry; - typedef typename Helper::Section Section; - - MachOObjectFile(MemoryBuffer *Object, error_code &ec); - static bool classof(const Binary *v); - - const Section *getSection(DataRefImpl DRI) const; - const SymbolTableEntry *getSymbolTableEntry(DataRefImpl DRI) const; - const RelocationEntry *getRelocation(DataRefImpl Rel) const; + virtual error_code getSymbolValue(DataRefImpl Symb, uint64_t &Val) const; + virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; + virtual error_code getSectionName(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAddress(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const; virtual error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const; virtual error_code getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const; virtual error_code isSectionText(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionData(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionBSS(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionRequiredForExecution(DataRefImpl Sec, + bool &Res) const; + virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const; virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const; + virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const; + virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, + bool &Result) const; + virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const; virtual relocation_iterator getSectionRelEnd(DataRefImpl Sec) const; + + virtual error_code getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const; virtual error_code getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const; virtual error_code getRelocationType(DataRefImpl Rel, uint64_t &Res) const; virtual error_code getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const; + virtual error_code getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const; virtual error_code getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const; virtual error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const; - virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const; - virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; - virtual error_code getSectionNext(DataRefImpl Sec, SectionRef &Res) const; - virtual section_iterator begin_sections() const; - void moveToNextSection(DataRefImpl &DRI) const; -}; - -typedef MachOObjectFileMiddle MachOObjectFileLE; -typedef MachOObjectFileMiddle MachOObjectFileBE; - -typedef MachOObjectFile > - MachOObjectFileLE32; -typedef MachOObjectFile > - MachOObjectFileBE32; -typedef MachOObjectFile > - MachOObjectFileLE64; -typedef MachOObjectFile > - MachOObjectFileBE64; - -template -MachOObjectFileMiddle::MachOObjectFileMiddle(MemoryBuffer *O, - bool Is64Bits, - error_code &ec) : - MachOObjectFileBase(O, TargetEndianness == support::little, Is64Bits, ec) { -} - -template -const typename MachOObjectFileMiddle::SymbolTableEntryBase * -MachOObjectFileMiddle::getSymbolTableEntryBase(DataRefImpl DRI) const { - const LoadCommand *L = getLoadCommandInfo(DRI.d.a); - const SymtabLoadCommand *S = reinterpret_cast(L); - - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = is64Bit() ? - sizeof(MachOObjectFileLE64::SymbolTableEntry) : - sizeof(MachOObjectFileLE32::SymbolTableEntry); - - uint64_t Offset = S->SymbolTableOffset + Index * SymbolTableEntrySize; - StringRef Data = getData(Offset, SymbolTableEntrySize); - return reinterpret_cast(Data.data()); -} - -template -const typename MachOObjectFileMiddle::Header * -MachOObjectFileMiddle::getHeader() const { - StringRef Data = getData(0, sizeof(Header)); - return reinterpret_cast(Data.data()); -} - -template -const typename MachOObjectFileMiddle::LoadCommand * -MachOObjectFileMiddle::getLoadCommandInfo(unsigned Index) const { - assert(Index < getHeader()->NumLoadCommands); - uint64_t Offset; - uint64_t NewOffset = getHeaderSize(); - const LoadCommand *Load; - unsigned I = 0; - do { - Offset = NewOffset; - StringRef Data = getData(Offset, sizeof(MachOObjectFileLE::LoadCommand)); - Load = reinterpret_cast(Data.data()); - NewOffset = Offset + Load->Size; - ++I; - } while (I != Index + 1); - - return reinterpret_cast(Load); -} - -template -const typename MachOObjectFileMiddle::RelocationEntry * -MachOObjectFileMiddle::getRelocation(DataRefImpl Rel) const { - if (const MachOObjectFile > *O = - dyn_cast > >(this)) - return O->getRelocation(Rel); - - const MachOObjectFile > *O = - cast > >(this); - return O->getRelocation(Rel); -} - -template -bool -MachOObjectFileMiddle::isRelocationScattered(const RelocationEntry *RE) - const { - if (this->getCPUType() == llvm::MachO::CPUTypeX86_64) - return false; - return RE->Address & macho::RF_Scattered; -} - -template -bool -MachOObjectFileMiddle::isRelocationPCRel(const RelocationEntry *RE) const { - typedef MachOObjectFileMiddle ObjType; - if (isRelocationScattered(RE)) { - const typename MachOObjectFileMiddle::ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->PCRel; - } - return RE->PCRel; -} - -template -unsigned -MachOObjectFileMiddle::getRelocationLength(const RelocationEntry *RE) const { - typedef MachOObjectFileMiddle ObjType; - if (isRelocationScattered(RE)) { - const typename ObjType::ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->Length; - } - return RE->Length; -} - -template -unsigned -MachOObjectFileMiddle::getRelocationTypeImpl(const RelocationEntry *RE) - const { - typedef MachOObjectFileMiddle ObjType; - if (isRelocationScattered(RE)) { - const typename ObjType::ScatteredRelocationEntry *SRE = - reinterpret_cast(RE); - return SRE->Type; - } - return RE->Type; -} - -// Helper to advance a section or symbol iterator multiple increments at a time. -template -template -error_code MachOObjectFileMiddle::advance(T &it, size_t Val) { - error_code ec; - while (Val--) { - it.increment(ec); - } - return ec; -} - -template -template -void MachOObjectFileMiddle::advanceTo(T &it, size_t Val) { - if (error_code ec = advance(it, Val)) - report_fatal_error(ec.message()); -} - -template -void -MachOObjectFileMiddle::printRelocationTargetName(const RelocationEntry *RE, - raw_string_ostream &fmt) const { - bool IsScattered = isRelocationScattered(RE); - - // Target of a scattered relocation is an address. In the interest of - // generating pretty output, scan through the symbol table looking for a - // symbol that aligns with that address. If we find one, print it. - // Otherwise, we just print the hex address of the target. - if (IsScattered) { - uint32_t Val = RE->SymbolNum; - - error_code ec; - for (symbol_iterator SI = begin_symbols(), SE = end_symbols(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - // If we couldn't find a symbol that this relocation refers to, try - // to find a section beginning instead. - for (section_iterator SI = begin_sections(), SE = end_sections(); SI != SE; - SI.increment(ec)) { - if (ec) report_fatal_error(ec.message()); - - uint64_t Addr; - StringRef Name; - - if ((ec = SI->getAddress(Addr))) - report_fatal_error(ec.message()); - if (Addr != Val) continue; - if ((ec = SI->getName(Name))) - report_fatal_error(ec.message()); - fmt << Name; - return; - } - - fmt << format("0x%x", Val); - return; - } - - StringRef S; - bool isExtern = RE->External; - uint64_t Val = RE->Address; - - if (isExtern) { - symbol_iterator SI = begin_symbols(); - advanceTo(SI, Val); - SI->getName(S); - } else { - section_iterator SI = begin_sections(); - advanceTo(SI, Val); - SI->getName(S); - } - - fmt << S; -} - -template -const typename MachOObjectFileMiddle::SectionBase * -MachOObjectFileMiddle::getSectionBase(DataRefImpl DRI) const { - uintptr_t CommandAddr = - reinterpret_cast(getLoadCommandInfo(DRI.d.a)); - - bool Is64 = is64Bit(); - unsigned SegmentLoadSize = - Is64 ? sizeof(MachOObjectFileLE64::SegmentLoadCommand) : - sizeof(MachOObjectFileLE32::SegmentLoadCommand); - unsigned SectionSize = Is64 ? sizeof(MachOObjectFileLE64::Section) : - sizeof(MachOObjectFileLE32::Section); - - uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + DRI.d.b * SectionSize; - return reinterpret_cast(SectionAddr); -} - -template -unsigned MachOObjectFileMiddle::getCPUType() const { - return getHeader()->CPUType; -} - -template -void MachOObjectFileMiddle::moveToNextSymbol(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *L = getLoadCommandInfo(DRI.d.a); - if (L->Type == macho::LCT_Symtab) { - const SymtabLoadCommand *S = - reinterpret_cast(L); - if (DRI.d.b < S->NumSymbolTableEntries) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} - -template -StringRef -MachOObjectFileMiddle::getSectionFinalSegmentName(DataRefImpl Sec) const { - ArrayRef Raw = getSectionRawFinalSegmentName(Sec); - return parseSegmentOrSectionName(Raw.data()); -} - -template -ArrayRef -MachOObjectFileMiddle::getSectionRawName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef(Base->Name); -} - -template -ArrayRef -MachOObjectFileMiddle::getSectionRawFinalSegmentName(DataRefImpl Sec) const { - const SectionBase *Base = getSectionBase(Sec); - return ArrayRef(Base->SegmentName); -} - -template -error_code MachOObjectFileMiddle::getSymbolFlags(DataRefImpl DRI, - uint32_t &Result) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(DRI); - - uint8_t MachOType = Entry->Type; - uint16_t MachOFlags = Entry->Flags; - - // TODO: Correctly set SF_ThreadLocal - Result = SymbolRef::SF_None; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Undefined; - - if (MachOFlags & macho::STF_StabsEntryMask) - Result |= SymbolRef::SF_FormatSpecific; - - if (MachOType & MachO::NlistMaskExternal) { - Result |= SymbolRef::SF_Global; - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Common; - } - - if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) - Result |= SymbolRef::SF_Weak; - - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) - Result |= SymbolRef::SF_Absolute; - - return object_error::success; -} - -template -error_code MachOObjectFileMiddle::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t n_type = Entry->Type; - - Res = SymbolRef::ST_Other; - - // If this is a STAB debugging symbol, we can do nothing more. - if (n_type & MachO::NlistMaskStab) { - Res = SymbolRef::ST_Debug; - return object_error::success; - } - - switch (n_type & MachO::NlistMaskType) { - case MachO::NListTypeUndefined : - Res = SymbolRef::ST_Unknown; - break; - case MachO::NListTypeSection : - Res = SymbolRef::ST_Function; - break; - } - return object_error::success; -} - -template -error_code MachOObjectFileMiddle::getSymbolName(DataRefImpl Symb, - StringRef &Res) const { - const LoadCommand *L = getLoadCommandInfo(Symb.d.a); - const SymtabLoadCommand *S = reinterpret_cast(L); - StringRef StringTable = getData(S->StringTableOffset, S->StringTableSize); - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - const char *Start = &StringTable.data()[Entry->StringIndex]; - Res = StringRef(Start); - return object_error::success; -} - -template -error_code -MachOObjectFileMiddle::getSymbolSection(DataRefImpl Symb, - section_iterator &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t index = Entry->SectionIndex; - - if (index == 0) - Res = end_sections(); - else - Res = section_iterator(SectionRef(Sections[index-1], this)); - - return object_error::success; -} - - -template -error_code MachOObjectFileMiddle::getSymbolNMTypeChar(DataRefImpl Symb, - char &Res) const { - const SymbolTableEntryBase *Entry = getSymbolTableEntryBase(Symb); - uint8_t Type = Entry->Type; - uint16_t Flags = Entry->Flags; - - char Char; - switch (Type & macho::STF_TypeMask) { - case macho::STT_Undefined: - Char = 'u'; - break; - case macho::STT_Absolute: - case macho::STT_Section: - Char = 's'; - break; - default: - Char = '?'; - break; - } - - if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) - Char = toupper(static_cast(Char)); - Res = Char; - return object_error::success; -} - -template -error_code -MachOObjectFileMiddle::getSectionName(DataRefImpl Sec, - StringRef &Result) const { - ArrayRef Raw = getSectionRawName(Sec); - Result = parseSegmentOrSectionName(Raw.data()); - return object_error::success; -} - -template -error_code MachOObjectFileMiddle::getSymbolNext(DataRefImpl Symb, - SymbolRef &Res) const { - Symb.d.b++; - moveToNextSymbol(Symb); - Res = SymbolRef(Symb, this); - return object_error::success; -} - -template -symbol_iterator MachOObjectFileMiddle::begin_symbols() const { - // DRI.d.a = segment number; DRI.d.b = symbol index. - DataRefImpl DRI; - moveToNextSymbol(DRI); - return symbol_iterator(SymbolRef(DRI, this)); -} - -template -unsigned MachOObjectFileMiddle::getArch() const { - switch (getCPUType()) { - case llvm::MachO::CPUTypeI386: - return Triple::x86; - case llvm::MachO::CPUTypeX86_64: - return Triple::x86_64; - case llvm::MachO::CPUTypeARM: - return Triple::arm; - case llvm::MachO::CPUTypePowerPC: - return Triple::ppc; - case llvm::MachO::CPUTypePowerPC64: - return Triple::ppc64; - default: - return Triple::UnknownArch; - } -} - -template -StringRef MachOObjectFileMiddle::getFileFormatName() const { - unsigned CPUType = getCPUType(); - if (!is64Bit()) { - switch (CPUType) { - case llvm::MachO::CPUTypeI386: - return "Mach-O 32-bit i386"; - case llvm::MachO::CPUTypeARM: - return "Mach-O arm"; - case llvm::MachO::CPUTypePowerPC: - return "Mach-O 32-bit ppc"; - default: - assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && - "64-bit object file when we're not 64-bit?"); - return "Mach-O 32-bit unknown"; - } - } - - // Make sure the cpu type has the correct mask. - assert((CPUType & llvm::MachO::CPUArchABI64) - == llvm::MachO::CPUArchABI64 && - "32-bit object file when we're 64-bit?"); - - switch (CPUType) { - case llvm::MachO::CPUTypeX86_64: - return "Mach-O 64-bit x86-64"; - case llvm::MachO::CPUTypePowerPC64: - return "Mach-O 64-bit ppc64"; - default: - return "Mach-O 64-bit unknown"; - } -} - -template -symbol_iterator MachOObjectFileMiddle::end_symbols() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return symbol_iterator(SymbolRef(DRI, this)); -} - -template -section_iterator MachOObjectFileMiddle::end_sections() const { - DataRefImpl DRI; - DRI.d.a = getHeader()->NumLoadCommands; - return section_iterator(SectionRef(DRI, this)); -} - -template -bool MachOObjectFileMiddle::classof(const Binary *v) { - return isa > >(v) || - isa > >(v); -} - -template -MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, - error_code &ec) : - MachOObjectFileMiddle(Object, Is64Bits, ec) { - DataRefImpl DRI; - moveToNextSection(DRI); - uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - this->Sections.push_back(DRI); - DRI.d.b++; - moveToNextSection(DRI); - } -} - -template -bool MachOObjectFile::classof(const Binary *v) { - return v->getType() == - Base::getMachOType(TargetEndianness == support::little, Is64Bits); -} - -template -const typename MachOObjectFile::Section * -MachOObjectFile::getSection(DataRefImpl DRI) const { - const SectionBase *Addr = this->getSectionBase(DRI); - return reinterpret_cast(Addr); -} - -template -const typename MachOObjectFile::SymbolTableEntry * -MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const SymbolTableEntryBase *Base = this->getSymbolTableEntryBase(DRI); - return reinterpret_cast(Base); -} - -template -const typename MachOObjectFile::RelocationEntry * -MachOObjectFile::getRelocation(DataRefImpl Rel) const { - const Section *Sect = getSection(this->Sections[Rel.d.b]); - uint32_t RelOffset = Sect->RelocationTableOffset; - uint64_t Offset = RelOffset + Rel.d.a * sizeof(RelocationEntry); - StringRef Data = this->getData(Offset, sizeof(RelocationEntry)); - return reinterpret_cast(Data.data()); -} - -template -error_code -MachOObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const { - const Section *Sect = getSection(Sec); - Res = Sect->Address; - return object_error::success; -} - -template -error_code -MachOObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Res) const { - const Section *Sect = getSection(Sec); - Res = Sect->Size; - return object_error::success; -} -template -error_code -MachOObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Res) const { - const Section *Sect = getSection(Sec); - Res = this->getData(Sect->Offset, Sect->Size); - return object_error::success; -} - -template -error_code -MachOObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const { - const Section *Sect = getSection(Sec); - Res = uint64_t(1) << Sect->Align; - return object_error::success; -} - -template -error_code -MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { - const Section *Sect = getSection(Sec); - Res = Sect->Flags & macho::SF_PureInstructions; - return object_error::success; -} - -template -error_code -MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { - const Section *Sect = getSection(Sec); - unsigned SectionType = Sect->Flags & MachO::SectionFlagMaskSectionType; - Res = SectionType == MachO::SectionTypeZeroFill || - SectionType == MachO::SectionTypeZeroFillLarge; - return object_error::success; -} - -template -relocation_iterator -MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - const Section *Sect = getSection(Sec); - uint32_t LastReloc = Sect->NumRelocationTableEntries; - DataRefImpl Ret; - Ret.d.a = LastReloc; - Ret.d.b = this->getSectionIndex(Sec); - return relocation_iterator(RelocationRef(Ret, this)); -} - -template -error_code -MachOObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { - const Section *Sect = getSection(this->Sections[Rel.d.b]); - uint64_t SectAddress = Sect->Address; - const RelocationEntry *RE = getRelocation(Rel); - - uint64_t RelAddr; - if (this->isRelocationScattered(RE)) - RelAddr = RE->Address & 0xFFFFFF; - else - RelAddr = RE->Address; - - Res = SectAddress + RelAddr; - return object_error::success; -} - -template -error_code -MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { - const RelocationEntry *RE = getRelocation(Rel); - if (this->isRelocationScattered(RE)) - Res = RE->Address & 0xFFFFFF; - else - Res = RE->Address; - return object_error::success; -} - -template -error_code -MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const { - const RelocationEntry *RE = getRelocation(Rel); - uint32_t SymbolIdx = RE->SymbolNum; - bool isExtern = RE->External; - - DataRefImpl Sym; - this->moveToNextSymbol(Sym); - if (isExtern) { - for (unsigned i = 0; i < SymbolIdx; i++) { - Sym.d.b++; - this->moveToNextSymbol(Sym); - assert(Sym.d.a < this->getHeader()->NumLoadCommands && - "Relocation symbol index out of range!"); - } - } - Res = SymbolRef(Sym, this); - return object_error::success; -} - -template -error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { - const RelocationEntry *RE = getRelocation(Rel); - Res = this->getRelocationTypeImpl(RE); - return object_error::success; -} - -template -error_code -MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const { - // TODO: Support scattered relocations. - StringRef res; - const RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = this->getArch(); - - unsigned r_type = this->getRelocationTypeImpl(RE); - - switch (Arch) { - case Triple::x86: { - static const char *const Table[] = { - "GENERIC_RELOC_VANILLA", - "GENERIC_RELOC_PAIR", - "GENERIC_RELOC_SECTDIFF", - "GENERIC_RELOC_PB_LA_PTR", - "GENERIC_RELOC_LOCAL_SECTDIFF", - "GENERIC_RELOC_TLV" }; - - if (r_type > 6) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::x86_64: { - static const char *const Table[] = { - "X86_64_RELOC_UNSIGNED", - "X86_64_RELOC_SIGNED", - "X86_64_RELOC_BRANCH", - "X86_64_RELOC_GOT_LOAD", - "X86_64_RELOC_GOT", - "X86_64_RELOC_SUBTRACTOR", - "X86_64_RELOC_SIGNED_1", - "X86_64_RELOC_SIGNED_2", - "X86_64_RELOC_SIGNED_4", - "X86_64_RELOC_TLV" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::arm: { - static const char *const Table[] = { - "ARM_RELOC_VANILLA", - "ARM_RELOC_PAIR", - "ARM_RELOC_SECTDIFF", - "ARM_RELOC_LOCAL_SECTDIFF", - "ARM_RELOC_PB_LA_PTR", - "ARM_RELOC_BR24", - "ARM_THUMB_RELOC_BR22", - "ARM_THUMB_32BIT_BRANCH", - "ARM_RELOC_HALF", - "ARM_RELOC_HALF_SECTDIFF" }; - - if (r_type > 9) - res = "Unknown"; - else - res = Table[r_type]; - break; - } - case Triple::ppc: { - static const char *const Table[] = { - "PPC_RELOC_VANILLA", - "PPC_RELOC_PAIR", - "PPC_RELOC_BR14", - "PPC_RELOC_BR24", - "PPC_RELOC_HI16", - "PPC_RELOC_LO16", - "PPC_RELOC_HA16", - "PPC_RELOC_LO14", - "PPC_RELOC_SECTDIFF", - "PPC_RELOC_PB_LA_PTR", - "PPC_RELOC_HI16_SECTDIFF", - "PPC_RELOC_LO16_SECTDIFF", - "PPC_RELOC_HA16_SECTDIFF", - "PPC_RELOC_JBSR", - "PPC_RELOC_LO14_SECTDIFF", - "PPC_RELOC_LOCAL_SECTDIFF" }; - - res = Table[r_type]; - break; - } - case Triple::UnknownArch: - res = "Unknown"; - break; - } - Result.append(res.begin(), res.end()); - return object_error::success; -} - -template -error_code -MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { - const RelocationEntry *RE = getRelocation(Rel); - - unsigned Arch = this->getArch(); - bool IsScattered = this->isRelocationScattered(RE); - - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - - unsigned Type = this->getRelocationTypeImpl(RE); - bool IsPCRel = this->isRelocationPCRel(RE); - - // Determine any addends that should be displayed with the relocation. - // These require decoding the relocation type, which is triple-specific. - - // X86_64 has entirely custom relocation types. - if (Arch == Triple::x86_64) { - bool isPCRel = RE->PCRel; - - switch (Type) { - case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD - case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT - this->printRelocationTargetName(RE, fmt); - fmt << "@GOT"; - if (isPCRel) fmt << "PCREL"; - break; - } - case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const RelocationEntry *RENext = getRelocation(RelNext); - - // X86_64_SUBTRACTOR must be followed by a relocation of type - // X86_64_RELOC_UNSIGNED. - // NOTE: Scattered relocations don't exist on x86_64. - unsigned RType = RENext->Type; - if (RType != 0) - report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " - "X86_64_RELOC_SUBTRACTOR."); - - // The X86_64_RELOC_UNSIGNED contains the minuend symbol, - // X86_64_SUBTRACTOR contains to the subtrahend. - this->printRelocationTargetName(RENext, fmt); - fmt << "-"; - this->printRelocationTargetName(RE, fmt); - break; - } - case macho::RIT_X86_64_TLV: - this->printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (isPCRel) fmt << "P"; - break; - case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 - this->printRelocationTargetName(RE, fmt); - fmt << "-1"; - break; - case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 - this->printRelocationTargetName(RE, fmt); - fmt << "-2"; - break; - case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 - this->printRelocationTargetName(RE, fmt); - fmt << "-4"; - break; - default: - this->printRelocationTargetName(RE, fmt); - break; - } - // X86 and ARM share some relocation types in common. - } else if (Arch == Triple::x86 || Arch == Triple::arm) { - // Generic relocation types... - switch (Type) { - case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info - return object_error::success; - case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; - else - RType = RENext->Type; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_SECTDIFF."); - - this->printRelocationTargetName(RE, fmt); - fmt << "-"; - this->printRelocationTargetName(RENext, fmt); - break; - } - } - - if (Arch == Triple::x86) { - // All X86 relocations that need special printing were already - // handled in the generic code. - switch (Type) { - case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const RelocationEntry *RENext = getRelocation(RelNext); - - // X86 sect diff's must be followed by a relocation of type - // GENERIC_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; - else - RType = RENext->Type; - if (RType != 1) - report_fatal_error("Expected GENERIC_RELOC_PAIR after " - "GENERIC_RELOC_LOCAL_SECTDIFF."); - - this->printRelocationTargetName(RE, fmt); - fmt << "-"; - this->printRelocationTargetName(RENext, fmt); - break; - } - case macho::RIT_Generic_TLV: { - this->printRelocationTargetName(RE, fmt); - fmt << "@TLV"; - if (IsPCRel) fmt << "P"; - break; - } - default: - this->printRelocationTargetName(RE, fmt); - } - } else { // ARM-specific relocations - switch (Type) { - case macho::RIT_ARM_Half: // ARM_RELOC_HALF - case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF - // Half relocations steal a bit from the length field to encode - // whether this is an upper16 or a lower16 relocation. - bool isUpper; - if (IsScattered) - isUpper = (RE->Address >> 28) & 1; - else - isUpper = (RE->Length >> 1) & 1; - - if (isUpper) - fmt << ":upper16:("; - else - fmt << ":lower16:("; - this->printRelocationTargetName(RE, fmt); - - DataRefImpl RelNext = Rel; - RelNext.d.a++; - const RelocationEntry *RENext = getRelocation(RelNext); - - // ARM half relocs must be followed by a relocation of type - // ARM_RELOC_PAIR. - bool isNextScattered = (Arch != Triple::x86_64) && - (RENext->Address & macho::RF_Scattered); - unsigned RType; - if (isNextScattered) - RType = (RENext->Address >> 24) & 0xF; - else - RType = RENext->Type; - - if (RType != 1) - report_fatal_error("Expected ARM_RELOC_PAIR after " - "GENERIC_RELOC_HALF"); - - // NOTE: The half of the target virtual address is stashed in the - // address field of the secondary relocation, but we can't reverse - // engineer the constant offset from it without decoding the movw/movt - // instruction to find the other half in its immediate field. - - // ARM_RELOC_HALF_SECTDIFF encodes the second section in the - // symbol/section pointer of the follow-on relocation. - if (Type == macho::RIT_ARM_HalfDifference) { - fmt << "-"; - this->printRelocationTargetName(RENext, fmt); - } - - fmt << ")"; - break; - } - default: { - this->printRelocationTargetName(RE, fmt); - } - } - } - } else - this->printRelocationTargetName(RE, fmt); - - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - return object_error::success; -} - -template -error_code -MachOObjectFile::getRelocationHidden(DataRefImpl Rel, - bool &Result) const { - const RelocationEntry *RE = getRelocation(Rel); - unsigned Arch = this->getArch(); - unsigned Type = this->getRelocationTypeImpl(RE); - - Result = false; - - // On arches that use the generic relocations, GENERIC_RELOC_PAIR - // is always hidden. - if (Arch == Triple::x86 || Arch == Triple::arm) { - if (Type == macho::RIT_Pair) Result = true; - } else if (Arch == Triple::x86_64) { - // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows - // an X864_64_RELOC_SUBTRACTOR. - if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { - DataRefImpl RelPrev = Rel; - RelPrev.d.a--; - const RelocationEntry *REPrev = this->getRelocation(RelPrev); + virtual error_code getLibraryNext(DataRefImpl LibData, LibraryRef &Res) const; + virtual error_code getLibraryPath(DataRefImpl LibData, StringRef &Res) const; - unsigned PrevType = REPrev->Type; + virtual symbol_iterator begin_symbols() const; + virtual symbol_iterator end_symbols() const; - if (PrevType == macho::RIT_X86_64_Subtractor) Result = true; - } - } + virtual symbol_iterator begin_dynamic_symbols() const; + virtual symbol_iterator end_dynamic_symbols() const; - return object_error::success; -} + virtual section_iterator begin_sections() const; + virtual section_iterator end_sections() const; -template -error_code -MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, - uint64_t &Res) const { - const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); - Res = Entry->Value; - if (Entry->SectionIndex) { - const Section *Sec = - this->getSection(this->Sections[Entry->SectionIndex-1]); - Res += Sec->Offset - Sec->Address; - } + virtual library_iterator begin_libraries_needed() const; + virtual library_iterator end_libraries_needed() const; - return object_error::success; -} + virtual uint8_t getBytesInAddress() const; -template -error_code -MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { - SymbolRef::Type ST; - this->getSymbolType(Symb, ST); - if (ST == SymbolRef::ST_Unknown) { - Result = false; - return object_error::success; - } + virtual StringRef getFileFormatName() const; + virtual unsigned getArch() const; - uint64_t SectBegin, SectEnd; - getSectionAddress(Sec, SectBegin); - getSectionSize(Sec, SectEnd); - SectEnd += SectBegin; + virtual StringRef getLoadName() const; - const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); - uint64_t SymAddr= Entry->Value; - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); + // In a MachO file, sections have a segment name. This is used in the .o + // files. They have a single segment, but this field specifies which segment + // a section should be put in in the final object. + StringRef getSectionFinalSegmentName(DataRefImpl Sec) const; - return object_error::success; -} + // Names are stored as 16 bytes. These returns the raw 16 bytes without + // interpreting them as a C string. + ArrayRef getSectionRawName(DataRefImpl Sec) const; + ArrayRef getSectionRawFinalSegmentName(DataRefImpl Sec) const; -template -error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const { - const SymbolTableEntry *Entry = getSymbolTableEntry(Symb); - Res = Entry->Value; - return object_error::success; -} + // MachO specific Info about relocations. + bool isRelocationScattered(const macho::RelocationEntry &RE) const; + unsigned getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const; + bool getPlainRelocationExternal(const macho::RelocationEntry &RE) const; + bool getScatteredRelocationScattered(const macho::RelocationEntry &RE) const; + uint32_t getScatteredRelocationValue(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationAddress(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; + unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; + + // Walk load commands. + LoadCommandInfo getFirstLoadCommandInfo() const; + LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; + + // MachO specific structures. + macho::Section getSection(DataRefImpl DRI) const; + macho::Section64 getSection64(DataRefImpl DRI) const; + macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; + macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; + macho::LinkeditDataLoadCommand + getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; + macho::RelocationEntry getRelocation(DataRefImpl Rel) const; + macho::Header getHeader() const; + macho::SymtabLoadCommand getSymtabLoadCommand() const; -template -error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, - uint64_t &Result) const { - uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; - uint64_t BeginOffset; - uint64_t EndOffset = 0; - uint8_t SectionIndex; + bool is64Bit() const; + void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - const SymbolTableEntry *Entry = getSymbolTableEntry(DRI); - BeginOffset = Entry->Value; - SectionIndex = Entry->SectionIndex; - if (!SectionIndex) { - uint32_t flags = SymbolRef::SF_None; - this->getSymbolFlags(DRI, flags); - if (flags & SymbolRef::SF_Common) - Result = Entry->Value; - else - Result = UnknownAddressOrSize; - return object_error::success; - } - // Unfortunately symbols are unsorted so we need to touch all - // symbols from load command - DRI.d.b = 0; - uint32_t Command = DRI.d.a; - while (Command == DRI.d.a) { - this->moveToNextSymbol(DRI); - if (DRI.d.a < LoadCommandCount) { - Entry = getSymbolTableEntry(DRI); - if (Entry->SectionIndex == SectionIndex && Entry->Value > BeginOffset) - if (!EndOffset || Entry->Value < EndOffset) - EndOffset = Entry->Value; - } - DRI.d.b++; - } - if (!EndOffset) { - uint64_t Size; - this->getSectionSize(this->Sections[SectionIndex-1], Size); - this->getSectionAddress(this->Sections[SectionIndex-1], EndOffset); - EndOffset += Size; + static bool classof(const Binary *v) { + return v->isMachO(); } - Result = EndOffset - BeginOffset; - return object_error::success; -} - -template -error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, - SectionRef &Res) const { - Sec.d.b++; - moveToNextSection(Sec); - Res = SectionRef(Sec, this); - return object_error::success; -} - -template -section_iterator MachOObjectFile::begin_sections() const { - DataRefImpl DRI; - moveToNextSection(DRI); - return section_iterator(SectionRef(DRI, this)); -} -template -void MachOObjectFile::moveToNextSection(DataRefImpl &DRI) const { - uint32_t LoadCommandCount = this->getHeader()->NumLoadCommands; - while (DRI.d.a < LoadCommandCount) { - const LoadCommand *Command = this->getLoadCommandInfo(DRI.d.a); - if (Command->Type == SegmentLoadType) { - const SegmentLoadCommand *SegmentLoadCmd = - reinterpret_cast(Command); - if (DRI.d.b < SegmentLoadCmd->NumSections) - return; - } - - DRI.d.a++; - DRI.d.b = 0; - } -} +private: + typedef SmallVector SectionList; + SectionList Sections; + const char *SymtabLoadCmd; +}; } } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 192e7555b4..f5910dd95d 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -15,9 +15,9 @@ #include "llvm/Object/MachO.h" #include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" +#include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" #include #include @@ -29,98 +29,222 @@ using namespace object; namespace llvm { namespace object { -MachOObjectFileBase::MachOObjectFileBase(MemoryBuffer *Object, - bool IsLittleEndian, bool Is64bits, - error_code &ec) - : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) { +struct SymbolTableEntryBase { + uint32_t StringIndex; + uint8_t Type; + uint8_t SectionIndex; + uint16_t Flags; +}; + +struct SectionBase { + char Name[16]; + char SegmentName[16]; +}; + +template +static void SwapValue(T &Value) { + Value = sys::SwapByteOrder(Value); } -bool MachOObjectFileBase::is64Bit() const { - return isa(this) || isa(this); +template +static void SwapStruct(T &Value); + +template<> +void SwapStruct(macho::RelocationEntry &H) { + SwapValue(H.Word0); + SwapValue(H.Word1); } -void MachOObjectFileBase::ReadULEB128s(uint64_t Index, - SmallVectorImpl &Out) const { - DataExtractor extractor(ObjectFile::getData(), true, 0); +template<> +void SwapStruct(macho::LoadCommand &L) { + SwapValue(L.Type); + SwapValue(L.Size); +} - uint32_t offset = Index; - uint64_t data = 0; - while (uint64_t delta = extractor.getULEB128(&offset)) { - data += delta; - Out.push_back(data); - } +template<> +void SwapStruct(SymbolTableEntryBase &S) { + SwapValue(S.StringIndex); + SwapValue(S.Flags); } -unsigned MachOObjectFileBase::getHeaderSize() const { - return is64Bit() ? macho::Header64Size : macho::Header32Size; +template<> +void SwapStruct(macho::Section &S) { + SwapValue(S.Address); + SwapValue(S.Size); + SwapValue(S.Offset); + SwapValue(S.Align); + SwapValue(S.RelocationTableOffset); + SwapValue(S.NumRelocationTableEntries); + SwapValue(S.Flags); + SwapValue(S.Reserved1); + SwapValue(S.Reserved2); } -StringRef MachOObjectFileBase::getData(size_t Offset, size_t Size) const { - return ObjectFile::getData().substr(Offset, Size); +template<> +void SwapStruct(macho::Section64 &S) { + SwapValue(S.Address); + SwapValue(S.Size); + SwapValue(S.Offset); + SwapValue(S.Align); + SwapValue(S.RelocationTableOffset); + SwapValue(S.NumRelocationTableEntries); + SwapValue(S.Flags); + SwapValue(S.Reserved1); + SwapValue(S.Reserved2); + SwapValue(S.Reserved3); } -ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { - StringRef Magic = Buffer->getBuffer().slice(0, 4); - error_code ec; - ObjectFile *Ret; - if (Magic == "\xFE\xED\xFA\xCE") - Ret = new MachOObjectFileBE32(Buffer, ec); - else if (Magic == "\xCE\xFA\xED\xFE") - Ret = new MachOObjectFileLE32(Buffer, ec); - else if (Magic == "\xFE\xED\xFA\xCF") - Ret = new MachOObjectFileBE64(Buffer, ec); - else if (Magic == "\xCF\xFA\xED\xFE") - Ret = new MachOObjectFileLE64(Buffer, ec); - else - return NULL; +template<> +void SwapStruct(macho::SymbolTableEntry &S) { + SwapValue(S.StringIndex); + SwapValue(S.Flags); + SwapValue(S.Value); +} - if (ec) - return NULL; - return Ret; +template<> +void SwapStruct(macho::Symbol64TableEntry &S) { + SwapValue(S.StringIndex); + SwapValue(S.Flags); + SwapValue(S.Value); } -/*===-- Symbols -----------------------------------------------------------===*/ +template<> +void SwapStruct(macho::Header &H) { + SwapValue(H.Magic); + SwapValue(H.CPUType); + SwapValue(H.CPUSubtype); + SwapValue(H.FileType); + SwapValue(H.NumLoadCommands); + SwapValue(H.SizeOfLoadCommands); + SwapValue(H.Flags); +} -error_code MachOObjectFileBase::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { - report_fatal_error("getSymbolValue unimplemented in MachOObjectFileBase"); +template<> +void SwapStruct(macho::SymtabLoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.SymbolTableOffset); + SwapValue(C.NumSymbolTableEntries); + SwapValue(C.StringTableOffset); + SwapValue(C.StringTableSize); } -symbol_iterator MachOObjectFileBase::begin_dynamic_symbols() const { - // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); +template<> +void SwapStruct(macho::LinkeditDataLoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.DataOffset); + SwapValue(C.DataSize); } -symbol_iterator MachOObjectFileBase::end_dynamic_symbols() const { - // TODO: implement - report_fatal_error("Dynamic symbols unimplemented in MachOObjectFileBase"); +template<> +void SwapStruct(macho::SegmentLoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.VMAddress); + SwapValue(C.VMSize); + SwapValue(C.FileOffset); + SwapValue(C.FileSize); + SwapValue(C.MaxVMProtection); + SwapValue(C.InitialVMProtection); + SwapValue(C.NumSections); + SwapValue(C.Flags); } -library_iterator MachOObjectFileBase::begin_libraries_needed() const { - // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); +template<> +void SwapStruct(macho::Segment64LoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.VMAddress); + SwapValue(C.VMSize); + SwapValue(C.FileOffset); + SwapValue(C.FileSize); + SwapValue(C.MaxVMProtection); + SwapValue(C.InitialVMProtection); + SwapValue(C.NumSections); + SwapValue(C.Flags); } -library_iterator MachOObjectFileBase::end_libraries_needed() const { - // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); +static bool isSwappedEndian(const MachOObjectFile *O) { + return O->isLittleEndian() != sys::IsLittleEndianHost; } -StringRef MachOObjectFileBase::getLoadName() const { - // TODO: Implement - report_fatal_error("get_load_name() unimplemented in MachOObjectFileBase"); +static macho::SegmentLoadCommand +getSegmentLoadCommand(const MachOObjectFile *O, + const MachOObjectFile::LoadCommandInfo &L) { + macho::SegmentLoadCommand Cmd; + memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand)); + if (isSwappedEndian(O)) + SwapStruct(Cmd); + return Cmd; +} + +static macho::Segment64LoadCommand +getSegment64LoadCommand(const MachOObjectFile *O, + const MachOObjectFile::LoadCommandInfo &L) { + macho::Segment64LoadCommand Cmd; + memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand)); + if (isSwappedEndian(O)) + SwapStruct(Cmd); + return Cmd; +} + +static uint32_t +getSegmentLoadCommandNumSections(const MachOObjectFile *O, + const MachOObjectFile::LoadCommandInfo &L) { + if (O->is64Bit()) { + macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L); + return S.NumSections; + } + macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L); + return S.NumSections; } -/*===-- Sections ----------------------------------------------------------===*/ +static const SectionBase * +getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, + unsigned Sec) { + uintptr_t CommandAddr = reinterpret_cast(L.Ptr); -std::size_t MachOObjectFileBase::getSectionIndex(DataRefImpl Sec) const { - SectionList::const_iterator loc = - std::find(Sections.begin(), Sections.end(), Sec); - assert(loc != Sections.end() && "Sec is not a valid section!"); - return std::distance(Sections.begin(), loc); + bool Is64 = O->is64Bit(); + unsigned SegmentLoadSize = Is64 ? sizeof(macho::Segment64LoadCommand) : + sizeof(macho::SegmentLoadCommand); + unsigned SectionSize = Is64 ? sizeof(macho::Section64) : + sizeof(macho::Section); + + uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; + return reinterpret_cast(SectionAddr); +} + +static const char *getPtr(const MachOObjectFile *O, size_t Offset) { + return O->getData().substr(Offset, 1).data(); +} + +static const char *getSymbolTableEntryPtr(const MachOObjectFile *O, + DataRefImpl DRI) { + macho::SymtabLoadCommand S = O->getSymtabLoadCommand(); + + unsigned Index = DRI.d.b; + + unsigned SymbolTableEntrySize = O->is64Bit() ? + sizeof(macho::Symbol64TableEntry) : + sizeof(macho::SymbolTableEntry); + + uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize; + return getPtr(O, Offset); +} + +static SymbolTableEntryBase +getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { + const char *P = getSymbolTableEntryPtr(O, DRI); + SymbolTableEntryBase Ret; + memcpy(&Ret, P, sizeof(SymbolTableEntryBase)); + if (isSwappedEndian(O)) + SwapStruct(Ret); + + return Ret; } -StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const { +static StringRef parseSegmentOrSectionName(const char *P) { if (P[15] == 0) // Null terminated. return P; @@ -128,14 +252,470 @@ StringRef MachOObjectFileBase::parseSegmentOrSectionName(const char *P) const { return StringRef(P, 16); } -error_code MachOObjectFileBase::isSectionData(DataRefImpl DRI, +// Helper to advance a section or symbol iterator multiple increments at a time. +template +static error_code advance(T &it, size_t Val) { + error_code ec; + while (Val--) { + it.increment(ec); + } + return ec; +} + +template +static void advanceTo(T &it, size_t Val) { + if (error_code ec = advance(it, Val)) + report_fatal_error(ec.message()); +} + +static unsigned getCPUType(const MachOObjectFile *O) { + return O->getHeader().CPUType; +} + +static void printRelocationTargetName(const MachOObjectFile *O, + const macho::RelocationEntry &RE, + raw_string_ostream &fmt) { + bool IsScattered = O->isRelocationScattered(RE); + + // Target of a scattered relocation is an address. In the interest of + // generating pretty output, scan through the symbol table looking for a + // symbol that aligns with that address. If we find one, print it. + // Otherwise, we just print the hex address of the target. + if (IsScattered) { + uint32_t Val = O->getPlainRelocationSymbolNum(RE); + + error_code ec; + for (symbol_iterator SI = O->begin_symbols(), SE = O->end_symbols(); + SI != SE; SI.increment(ec)) { + if (ec) report_fatal_error(ec.message()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + // If we couldn't find a symbol that this relocation refers to, try + // to find a section beginning instead. + for (section_iterator SI = O->begin_sections(), SE = O->end_sections(); + SI != SE; SI.increment(ec)) { + if (ec) report_fatal_error(ec.message()); + + uint64_t Addr; + StringRef Name; + + if ((ec = SI->getAddress(Addr))) + report_fatal_error(ec.message()); + if (Addr != Val) continue; + if ((ec = SI->getName(Name))) + report_fatal_error(ec.message()); + fmt << Name; + return; + } + + fmt << format("0x%x", Val); + return; + } + + StringRef S; + bool isExtern = O->getPlainRelocationExternal(RE); + uint64_t Val = O->getAnyRelocationAddress(RE); + + if (isExtern) { + symbol_iterator SI = O->begin_symbols(); + advanceTo(SI, Val); + SI->getName(S); + } else { + section_iterator SI = O->begin_sections(); + advanceTo(SI, Val); + SI->getName(S); + } + + fmt << S; +} + +static uint32_t getPlainRelocationAddress(const macho::RelocationEntry &RE) { + return RE.Word0; +} + +static unsigned +getScatteredRelocationAddress(const macho::RelocationEntry &RE) { + return RE.Word0 & 0xffffff; +} + +static bool getPlainRelocationPCRel(const MachOObjectFile *O, + const macho::RelocationEntry &RE) { + if (O->isLittleEndian()) + return (RE.Word1 >> 24) & 1; + return (RE.Word1 >> 7) & 1; +} + +static bool +getScatteredRelocationPCRel(const MachOObjectFile *O, + const macho::RelocationEntry &RE) { + return (RE.Word0 >> 30) & 1; +} + +static unsigned getPlainRelocationLength(const MachOObjectFile *O, + const macho::RelocationEntry &RE) { + if (O->isLittleEndian()) + return (RE.Word1 >> 25) & 3; + return (RE.Word1 >> 5) & 3; +} + +static unsigned +getScatteredRelocationLength(const macho::RelocationEntry &RE) { + return (RE.Word0 >> 28) & 3; +} + +static unsigned getPlainRelocationType(const MachOObjectFile *O, + const macho::RelocationEntry &RE) { + if (O->isLittleEndian()) + return RE.Word1 >> 28; + return RE.Word1 & 0xf; +} + +static unsigned getScatteredRelocationType(const macho::RelocationEntry &RE) { + return (RE.Word0 >> 24) & 0xf; +} + +static uint32_t getSectionFlags(const MachOObjectFile *O, + DataRefImpl Sec) { + if (O->is64Bit()) { + macho::Section64 Sect = O->getSection64(Sec); + return Sect.Flags; + } + macho::Section Sect = O->getSection(Sec); + return Sect.Flags; +} + +MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, + bool IsLittleEndian, bool Is64bits, + error_code &ec) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), + SymtabLoadCmd(NULL) { + uint32_t LoadCommandCount = this->getHeader().NumLoadCommands; + macho::LoadCommandType SegmentLoadType = is64Bit() ? + macho::LCT_Segment64 : macho::LCT_Segment; + + MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); + for (unsigned I = 0; I < LoadCommandCount; ++I) { + if (Load.C.Type == macho::LCT_Symtab) { + assert(!SymtabLoadCmd && "Multiple symbol tables"); + SymtabLoadCmd = Load.Ptr; + } + + if (Load.C.Type == SegmentLoadType) { + uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); + for (unsigned J = 0; J < NumSections; ++J) { + const SectionBase *Sec = getSectionBase(this, Load, J); + Sections.push_back(reinterpret_cast(Sec)); + } + } + Load = getNextLoadCommandInfo(Load); + } +} + +error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, + SymbolRef &Res) const { + Symb.d.b++; + Res = SymbolRef(Symb, this); + return object_error::success; +} + +error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, + StringRef &Res) const { + macho::SymtabLoadCommand S = getSymtabLoadCommand(); + const char *StringTable = getPtr(this, S.StringTableOffset); + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); + const char *Start = &StringTable[Entry.StringIndex]; + Res = StringRef(Start); + return object_error::success; +} + +error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, + uint64_t &Res) const { + if (is64Bit()) { + macho::Symbol64TableEntry Entry = getSymbol64TableEntry(Symb); + Res = Entry.Value; + } else { + macho::SymbolTableEntry Entry = getSymbolTableEntry(Symb); + Res = Entry.Value; + } + return object_error::success; +} + +error_code +MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, + uint64_t &Res) const { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); + getSymbolAddress(Symb, Res); + if (Entry.SectionIndex) { + uint64_t Delta; + DataRefImpl SecRel; + SecRel.d.a = Entry.SectionIndex-1; + if (is64Bit()) { + macho::Section64 Sec = getSection64(SecRel); + Delta = Sec.Offset - Sec.Address; + } else { + macho::Section Sec = getSection(SecRel); + Delta = Sec.Offset - Sec.Address; + } + + Res += Delta; + } + + return object_error::success; +} + +error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, + uint64_t &Result) const { + uint64_t BeginOffset; + uint64_t EndOffset = 0; + uint8_t SectionIndex; + + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); + uint64_t Value; + getSymbolAddress(DRI, Value); + + BeginOffset = Value; + + SectionIndex = Entry.SectionIndex; + if (!SectionIndex) { + uint32_t flags = SymbolRef::SF_None; + this->getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) + Result = Value; + else + Result = UnknownAddressOrSize; + return object_error::success; + } + // Unfortunately symbols are unsorted so we need to touch all + // symbols from load command + macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); + DRI.d.b = 0; + while (DRI.d.b <= Symtab.NumSymbolTableEntries) { + Entry = getSymbolTableEntryBase(this, DRI); + getSymbolAddress(DRI, Value); + if (Entry.SectionIndex == SectionIndex && Value > BeginOffset) + if (!EndOffset || Value < EndOffset) + EndOffset = Value; + DRI.d.b++; + } + if (!EndOffset) { + uint64_t Size; + DataRefImpl Sec; + Sec.d.a = SectionIndex-1; + getSectionSize(Sec, Size); + getSectionAddress(Sec, EndOffset); + EndOffset += Size; + } + Result = EndOffset - BeginOffset; + return object_error::success; +} + +error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, + SymbolRef::Type &Res) const { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); + uint8_t n_type = Entry.Type; + + Res = SymbolRef::ST_Other; + + // If this is a STAB debugging symbol, we can do nothing more. + if (n_type & MachO::NlistMaskStab) { + Res = SymbolRef::ST_Debug; + return object_error::success; + } + + switch (n_type & MachO::NlistMaskType) { + case MachO::NListTypeUndefined : + Res = SymbolRef::ST_Unknown; + break; + case MachO::NListTypeSection : + Res = SymbolRef::ST_Function; + break; + } + return object_error::success; +} + +error_code MachOObjectFile::getSymbolNMTypeChar(DataRefImpl Symb, + char &Res) const { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); + uint8_t Type = Entry.Type; + uint16_t Flags = Entry.Flags; + + char Char; + switch (Type & macho::STF_TypeMask) { + case macho::STT_Undefined: + Char = 'u'; + break; + case macho::STT_Absolute: + case macho::STT_Section: + Char = 's'; + break; + default: + Char = '?'; + break; + } + + if (Flags & (macho::STF_External | macho::STF_PrivateExtern)) + Char = toupper(static_cast(Char)); + Res = Char; + return object_error::success; +} + +error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, + uint32_t &Result) const { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); + + uint8_t MachOType = Entry.Type; + uint16_t MachOFlags = Entry.Flags; + + // TODO: Correctly set SF_ThreadLocal + Result = SymbolRef::SF_None; + + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) + Result |= SymbolRef::SF_Undefined; + + if (MachOFlags & macho::STF_StabsEntryMask) + Result |= SymbolRef::SF_FormatSpecific; + + if (MachOType & MachO::NlistMaskExternal) { + Result |= SymbolRef::SF_Global; + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) + Result |= SymbolRef::SF_Common; + } + + if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) + Result |= SymbolRef::SF_Weak; + + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeAbsolute) + Result |= SymbolRef::SF_Absolute; + + return object_error::success; +} + +error_code +MachOObjectFile::getSymbolSection(DataRefImpl Symb, + section_iterator &Res) const { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); + uint8_t index = Entry.SectionIndex; + + if (index == 0) { + Res = end_sections(); + } else { + DataRefImpl DRI; + DRI.d.a = index - 1; + Res = section_iterator(SectionRef(DRI, this)); + } + + return object_error::success; +} + +error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, + uint64_t &Val) const { + report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); +} + +error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, + SectionRef &Res) const { + Sec.d.a++; + Res = SectionRef(Sec, this); + return object_error::success; +} + +error_code +MachOObjectFile::getSectionName(DataRefImpl Sec, + StringRef &Result) const { + ArrayRef Raw = getSectionRawName(Sec); + Result = parseSegmentOrSectionName(Raw.data()); + return object_error::success; +} + +error_code +MachOObjectFile::getSectionAddress(DataRefImpl Sec, + uint64_t &Res) const { + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Res = Sect.Address; + } else { + macho::Section Sect = getSection(Sec); + Res = Sect.Address; + } + return object_error::success; +} + +error_code +MachOObjectFile::getSectionSize(DataRefImpl Sec, + uint64_t &Res) const { + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Res = Sect.Size; + } else { + macho::Section Sect = getSection(Sec); + Res = Sect.Size; + } + + return object_error::success; +} + +error_code +MachOObjectFile::getSectionContents(DataRefImpl Sec, + StringRef &Res) const { + uint32_t Offset; + uint64_t Size; + + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Offset = Sect.Offset; + Size = Sect.Size; + } else { + macho::Section Sect =getSection(Sec); + Offset = Sect.Offset; + Size = Sect.Size; + } + + Res = this->getData().substr(Offset, Size); + return object_error::success; +} + +error_code +MachOObjectFile::getSectionAlignment(DataRefImpl Sec, + uint64_t &Res) const { + uint32_t Align; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Align = Sect.Align; + } else { + macho::Section Sect = getSection(Sec); + Align = Sect.Align; + } + + Res = uint64_t(1) << Align; + return object_error::success; +} + +error_code +MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { + uint32_t Flags = getSectionFlags(this, Sec); + Res = Flags & macho::SF_PureInstructions; + return object_error::success; +} + +error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI, +error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. Result = false; @@ -143,21 +723,30 @@ error_code MachOObjectFileBase::isSectionBSS(DataRefImpl DRI, } error_code -MachOObjectFileBase::isSectionRequiredForExecution(DataRefImpl Sec, +MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, bool &Result) const { // FIXME: Unimplemented. Result = true; return object_error::success; } -error_code MachOObjectFileBase::isSectionVirtual(DataRefImpl Sec, +error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec, +error_code +MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { + uint32_t Flags = getSectionFlags(this, Sec); + unsigned SectionType = Flags & MachO::SectionFlagMaskSectionType; + Res = SectionType == MachO::SectionTypeZeroFill || + SectionType == MachO::SectionTypeZeroFillLarge; + return object_error::success; +} + +error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, bool &Result) const { // Consider using the code from isSectionText to look for __const sections. // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS @@ -168,44 +757,752 @@ error_code MachOObjectFileBase::isSectionReadOnlyData(DataRefImpl Sec, return object_error::success; } -relocation_iterator MachOObjectFileBase::getSectionRelBegin(DataRefImpl Sec) const { +error_code +MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb, + bool &Result) const { + SymbolRef::Type ST; + this->getSymbolType(Symb, ST); + if (ST == SymbolRef::ST_Unknown) { + Result = false; + return object_error::success; + } + + uint64_t SectBegin, SectEnd; + getSectionAddress(Sec, SectBegin); + getSectionSize(Sec, SectEnd); + SectEnd += SectBegin; + + uint64_t SymAddr; + getSymbolAddress(Symb, SymAddr); + Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); + + return object_error::success; +} + +relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { DataRefImpl ret; - ret.d.b = getSectionIndex(Sec); + ret.d.b = Sec.d.a; return relocation_iterator(RelocationRef(ret, this)); } +relocation_iterator +MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { + uint32_t LastReloc; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + LastReloc = Sect.NumRelocationTableEntries; + } else { + macho::Section Sect = getSection(Sec); + LastReloc = Sect.NumRelocationTableEntries; + } -/*===-- Relocations -------------------------------------------------------===*/ + DataRefImpl Ret; + Ret.d.a = LastReloc; + Ret.d.b = Sec.d.a; + return relocation_iterator(RelocationRef(Ret, this)); +} -error_code MachOObjectFileBase::getRelocationNext(DataRefImpl Rel, +error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, RelocationRef &Res) const { ++Rel.d.a; Res = RelocationRef(Rel, this); return object_error::success; } -error_code MachOObjectFileBase::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); +error_code +MachOObjectFile::getRelocationAddress(DataRefImpl Rel, + uint64_t &Res) const { + uint64_t SectAddress; + DataRefImpl Sec; + Sec.d.a = Rel.d.b; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + SectAddress = Sect.Address; + } else { + macho::Section Sect = getSection(Sec); + SectAddress = Sect.Address; + } + + macho::RelocationEntry RE = getRelocation(Rel); + uint64_t RelAddr = getAnyRelocationAddress(RE); + Res = SectAddress + RelAddr; + return object_error::success; } -error_code MachOObjectFileBase::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFileBase"); +error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, + uint64_t &Res) const { + macho::RelocationEntry RE = getRelocation(Rel); + Res = getAnyRelocationAddress(RE); + return object_error::success; } -error_code MachOObjectFileBase::getRelocationAdditionalInfo(DataRefImpl Rel, - int64_t &Res) const { +error_code +MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, + SymbolRef &Res) const { + macho::RelocationEntry RE = getRelocation(Rel); + uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); + bool isExtern = getPlainRelocationExternal(RE); + + DataRefImpl Sym; + if (isExtern) { + Sym.d.b = SymbolIdx; + } + Res = SymbolRef(Sym, this); + return object_error::success; +} + +error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, + uint64_t &Res) const { + macho::RelocationEntry RE = getRelocation(Rel); + Res = getAnyRelocationType(RE); + return object_error::success; +} + +error_code +MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const { + StringRef res; + uint64_t RType; + getRelocationType(Rel, RType); + + unsigned Arch = this->getArch(); + + switch (Arch) { + case Triple::x86: { + static const char *const Table[] = { + "GENERIC_RELOC_VANILLA", + "GENERIC_RELOC_PAIR", + "GENERIC_RELOC_SECTDIFF", + "GENERIC_RELOC_PB_LA_PTR", + "GENERIC_RELOC_LOCAL_SECTDIFF", + "GENERIC_RELOC_TLV" }; + + if (RType > 6) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::x86_64: { + static const char *const Table[] = { + "X86_64_RELOC_UNSIGNED", + "X86_64_RELOC_SIGNED", + "X86_64_RELOC_BRANCH", + "X86_64_RELOC_GOT_LOAD", + "X86_64_RELOC_GOT", + "X86_64_RELOC_SUBTRACTOR", + "X86_64_RELOC_SIGNED_1", + "X86_64_RELOC_SIGNED_2", + "X86_64_RELOC_SIGNED_4", + "X86_64_RELOC_TLV" }; + + if (RType > 9) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::arm: { + static const char *const Table[] = { + "ARM_RELOC_VANILLA", + "ARM_RELOC_PAIR", + "ARM_RELOC_SECTDIFF", + "ARM_RELOC_LOCAL_SECTDIFF", + "ARM_RELOC_PB_LA_PTR", + "ARM_RELOC_BR24", + "ARM_THUMB_RELOC_BR22", + "ARM_THUMB_32BIT_BRANCH", + "ARM_RELOC_HALF", + "ARM_RELOC_HALF_SECTDIFF" }; + + if (RType > 9) + res = "Unknown"; + else + res = Table[RType]; + break; + } + case Triple::ppc: { + static const char *const Table[] = { + "PPC_RELOC_VANILLA", + "PPC_RELOC_PAIR", + "PPC_RELOC_BR14", + "PPC_RELOC_BR24", + "PPC_RELOC_HI16", + "PPC_RELOC_LO16", + "PPC_RELOC_HA16", + "PPC_RELOC_LO14", + "PPC_RELOC_SECTDIFF", + "PPC_RELOC_PB_LA_PTR", + "PPC_RELOC_HI16_SECTDIFF", + "PPC_RELOC_LO16_SECTDIFF", + "PPC_RELOC_HA16_SECTDIFF", + "PPC_RELOC_JBSR", + "PPC_RELOC_LO14_SECTDIFF", + "PPC_RELOC_LOCAL_SECTDIFF" }; + + res = Table[RType]; + break; + } + case Triple::UnknownArch: + res = "Unknown"; + break; + } + Result.append(res.begin(), res.end()); + return object_error::success; +} + +error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, + int64_t &Res) const { Res = 0; return object_error::success; } +error_code +MachOObjectFile::getRelocationValueString(DataRefImpl Rel, + SmallVectorImpl &Result) const { + macho::RelocationEntry RE = getRelocation(Rel); + + unsigned Arch = this->getArch(); + + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + unsigned Type = this->getAnyRelocationType(RE); + bool IsPCRel = this->getAnyRelocationPCRel(RE); + + // Determine any addends that should be displayed with the relocation. + // These require decoding the relocation type, which is triple-specific. + + // X86_64 has entirely custom relocation types. + if (Arch == Triple::x86_64) { + bool isPCRel = getAnyRelocationPCRel(RE); + + switch (Type) { + case macho::RIT_X86_64_GOTLoad: // X86_64_RELOC_GOT_LOAD + case macho::RIT_X86_64_GOT: { // X86_64_RELOC_GOT + printRelocationTargetName(this, RE, fmt); + fmt << "@GOT"; + if (isPCRel) fmt << "PCREL"; + break; + } + case macho::RIT_X86_64_Subtractor: { // X86_64_RELOC_SUBTRACTOR + DataRefImpl RelNext = Rel; + RelNext.d.a++; + macho::RelocationEntry RENext = getRelocation(RelNext); + + // X86_64_SUBTRACTOR must be followed by a relocation of type + // X86_64_RELOC_UNSIGNED. + // NOTE: Scattered relocations don't exist on x86_64. + unsigned RType = getAnyRelocationType(RENext); + if (RType != 0) + report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " + "X86_64_RELOC_SUBTRACTOR."); + + // The X86_64_RELOC_UNSIGNED contains the minuend symbol, + // X86_64_SUBTRACTOR contains to the subtrahend. + printRelocationTargetName(this, RENext, fmt); + fmt << "-"; + printRelocationTargetName(this, RE, fmt); + break; + } + case macho::RIT_X86_64_TLV: + printRelocationTargetName(this, RE, fmt); + fmt << "@TLV"; + if (isPCRel) fmt << "P"; + break; + case macho::RIT_X86_64_Signed1: // X86_64_RELOC_SIGNED1 + printRelocationTargetName(this, RE, fmt); + fmt << "-1"; + break; + case macho::RIT_X86_64_Signed2: // X86_64_RELOC_SIGNED2 + printRelocationTargetName(this, RE, fmt); + fmt << "-2"; + break; + case macho::RIT_X86_64_Signed4: // X86_64_RELOC_SIGNED4 + printRelocationTargetName(this, RE, fmt); + fmt << "-4"; + break; + default: + printRelocationTargetName(this, RE, fmt); + break; + } + // X86 and ARM share some relocation types in common. + } else if (Arch == Triple::x86 || Arch == Triple::arm) { + // Generic relocation types... + switch (Type) { + case macho::RIT_Pair: // GENERIC_RELOC_PAIR - prints no info + return object_error::success; + case macho::RIT_Difference: { // GENERIC_RELOC_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + macho::RelocationEntry RENext = getRelocation(RelNext); -/*===-- Miscellaneous -----------------------------------------------------===*/ + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); -uint8_t MachOObjectFileBase::getBytesInAddress() const { + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_SECTDIFF."); + + printRelocationTargetName(this, RE, fmt); + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + break; + } + } + + if (Arch == Triple::x86) { + // All X86 relocations that need special printing were already + // handled in the generic code. + switch (Type) { + case macho::RIT_Generic_LocalDifference:{// GENERIC_RELOC_LOCAL_SECTDIFF + DataRefImpl RelNext = Rel; + RelNext.d.a++; + macho::RelocationEntry RENext = getRelocation(RelNext); + + // X86 sect diff's must be followed by a relocation of type + // GENERIC_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); + if (RType != 1) + report_fatal_error("Expected GENERIC_RELOC_PAIR after " + "GENERIC_RELOC_LOCAL_SECTDIFF."); + + printRelocationTargetName(this, RE, fmt); + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + break; + } + case macho::RIT_Generic_TLV: { + printRelocationTargetName(this, RE, fmt); + fmt << "@TLV"; + if (IsPCRel) fmt << "P"; + break; + } + default: + printRelocationTargetName(this, RE, fmt); + } + } else { // ARM-specific relocations + switch (Type) { + case macho::RIT_ARM_Half: // ARM_RELOC_HALF + case macho::RIT_ARM_HalfDifference: { // ARM_RELOC_HALF_SECTDIFF + // Half relocations steal a bit from the length field to encode + // whether this is an upper16 or a lower16 relocation. + bool isUpper = getAnyRelocationLength(RE) >> 1; + + if (isUpper) + fmt << ":upper16:("; + else + fmt << ":lower16:("; + printRelocationTargetName(this, RE, fmt); + + DataRefImpl RelNext = Rel; + RelNext.d.a++; + macho::RelocationEntry RENext = getRelocation(RelNext); + + // ARM half relocs must be followed by a relocation of type + // ARM_RELOC_PAIR. + unsigned RType = getAnyRelocationType(RENext); + if (RType != 1) + report_fatal_error("Expected ARM_RELOC_PAIR after " + "GENERIC_RELOC_HALF"); + + // NOTE: The half of the target virtual address is stashed in the + // address field of the secondary relocation, but we can't reverse + // engineer the constant offset from it without decoding the movw/movt + // instruction to find the other half in its immediate field. + + // ARM_RELOC_HALF_SECTDIFF encodes the second section in the + // symbol/section pointer of the follow-on relocation. + if (Type == macho::RIT_ARM_HalfDifference) { + fmt << "-"; + printRelocationTargetName(this, RENext, fmt); + } + + fmt << ")"; + break; + } + default: { + printRelocationTargetName(this, RE, fmt); + } + } + } + } else + printRelocationTargetName(this, RE, fmt); + + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + return object_error::success; +} + +error_code +MachOObjectFile::getRelocationHidden(DataRefImpl Rel, + bool &Result) const { + unsigned Arch = getArch(); + uint64_t Type; + getRelocationType(Rel, Type); + + Result = false; + + // On arches that use the generic relocations, GENERIC_RELOC_PAIR + // is always hidden. + if (Arch == Triple::x86 || Arch == Triple::arm) { + if (Type == macho::RIT_Pair) Result = true; + } else if (Arch == Triple::x86_64) { + // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows + // an X864_64_RELOC_SUBTRACTOR. + if (Type == macho::RIT_X86_64_Unsigned && Rel.d.a > 0) { + DataRefImpl RelPrev = Rel; + RelPrev.d.a--; + uint64_t PrevType; + getRelocationType(RelPrev, PrevType); + if (PrevType == macho::RIT_X86_64_Subtractor) + Result = true; + } + } + + return object_error::success; +} + +error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, + LibraryRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, + StringRef &Res) const { + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +symbol_iterator MachOObjectFile::begin_symbols() const { + // DRI.d.a = segment number; DRI.d.b = symbol index. + DataRefImpl DRI; + return symbol_iterator(SymbolRef(DRI, this)); +} + +symbol_iterator MachOObjectFile::end_symbols() const { + DataRefImpl DRI; + if (SymtabLoadCmd) { + macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); + DRI.d.b = Symtab.NumSymbolTableEntries; + } + return symbol_iterator(SymbolRef(DRI, this)); +} + +symbol_iterator MachOObjectFile::begin_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +symbol_iterator MachOObjectFile::end_dynamic_symbols() const { + // TODO: implement + report_fatal_error("Dynamic symbols unimplemented in MachOObjectFile"); +} + +section_iterator MachOObjectFile::begin_sections() const { + DataRefImpl DRI; + return section_iterator(SectionRef(DRI, this)); +} + +section_iterator MachOObjectFile::end_sections() const { + DataRefImpl DRI; + DRI.d.a = Sections.size(); + return section_iterator(SectionRef(DRI, this)); +} + +library_iterator MachOObjectFile::begin_libraries_needed() const { + // TODO: implement + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +library_iterator MachOObjectFile::end_libraries_needed() const { + // TODO: implement + report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); +} + +uint8_t MachOObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } +StringRef MachOObjectFile::getFileFormatName() const { + unsigned CPUType = getCPUType(this); + if (!is64Bit()) { + switch (CPUType) { + case llvm::MachO::CPUTypeI386: + return "Mach-O 32-bit i386"; + case llvm::MachO::CPUTypeARM: + return "Mach-O arm"; + case llvm::MachO::CPUTypePowerPC: + return "Mach-O 32-bit ppc"; + default: + assert((CPUType & llvm::MachO::CPUArchABI64) == 0 && + "64-bit object file when we're not 64-bit?"); + return "Mach-O 32-bit unknown"; + } + } + + // Make sure the cpu type has the correct mask. + assert((CPUType & llvm::MachO::CPUArchABI64) + == llvm::MachO::CPUArchABI64 && + "32-bit object file when we're 64-bit?"); + + switch (CPUType) { + case llvm::MachO::CPUTypeX86_64: + return "Mach-O 64-bit x86-64"; + case llvm::MachO::CPUTypePowerPC64: + return "Mach-O 64-bit ppc64"; + default: + return "Mach-O 64-bit unknown"; + } +} + +unsigned MachOObjectFile::getArch() const { + switch (getCPUType(this)) { + case llvm::MachO::CPUTypeI386: + return Triple::x86; + case llvm::MachO::CPUTypeX86_64: + return Triple::x86_64; + case llvm::MachO::CPUTypeARM: + return Triple::arm; + case llvm::MachO::CPUTypePowerPC: + return Triple::ppc; + case llvm::MachO::CPUTypePowerPC64: + return Triple::ppc64; + default: + return Triple::UnknownArch; + } +} + +StringRef MachOObjectFile::getLoadName() const { + // TODO: Implement + report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); +} + +StringRef +MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { + ArrayRef Raw = getSectionRawFinalSegmentName(Sec); + return parseSegmentOrSectionName(Raw.data()); +} + +ArrayRef +MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { + const SectionBase *Base = + reinterpret_cast(Sections[Sec.d.a]); + return ArrayRef(Base->Name); +} + +ArrayRef +MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { + const SectionBase *Base = + reinterpret_cast(Sections[Sec.d.a]); + return ArrayRef(Base->SegmentName); +} + +bool +MachOObjectFile::isRelocationScattered(const macho::RelocationEntry &RE) + const { + if (getCPUType(this) == llvm::MachO::CPUTypeX86_64) + return false; + return getPlainRelocationAddress(RE) & macho::RF_Scattered; +} + +unsigned MachOObjectFile::getPlainRelocationSymbolNum(const macho::RelocationEntry &RE) const { + if (isLittleEndian()) + return RE.Word1 & 0xffffff; + return RE.Word1 >> 8; +} + +bool MachOObjectFile::getPlainRelocationExternal(const macho::RelocationEntry &RE) const { + if (isLittleEndian()) + return (RE.Word1 >> 27) & 1; + return (RE.Word1 >> 4) & 1; +} + +bool +MachOObjectFile::getScatteredRelocationScattered(const macho::RelocationEntry &RE) const { + return RE.Word0 >> 31; +} + +uint32_t +MachOObjectFile::getScatteredRelocationValue(const macho::RelocationEntry &RE) const { + return RE.Word1; +} + +unsigned +MachOObjectFile::getAnyRelocationAddress(const macho::RelocationEntry &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationAddress(RE); + return getPlainRelocationAddress(RE); +} + +unsigned +MachOObjectFile::getAnyRelocationPCRel(const macho::RelocationEntry &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationPCRel(this, RE); + return getPlainRelocationPCRel(this, RE); +} + +unsigned +MachOObjectFile::getAnyRelocationLength(const macho::RelocationEntry &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationLength(RE); + return getPlainRelocationLength(this, RE); +} + +unsigned +MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const { + if (isRelocationScattered(RE)) + return getScatteredRelocationType(RE); + return getPlainRelocationType(this, RE); +} + +MachOObjectFile::LoadCommandInfo +MachOObjectFile::getFirstLoadCommandInfo() const { + MachOObjectFile::LoadCommandInfo Load; + + unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size; + Load.Ptr = getPtr(this, HeaderSize); + memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand)); + if (isSwappedEndian(this)) + SwapStruct(Load.C); + return Load; +} + +MachOObjectFile::LoadCommandInfo +MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { + MachOObjectFile::LoadCommandInfo Next; + Next.Ptr = L.Ptr + L.C.Size; + memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand)); + if (isSwappedEndian(this)) + SwapStruct(Next.C); + return Next; +} + +macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const { + const SectionBase *Addr = + reinterpret_cast(Sections[DRI.d.a]); + macho::Section Ret; + memcpy(&Ret, Addr, sizeof(macho::Section)); + if (isSwappedEndian(this)) + SwapStruct(Ret); + return Ret; +} + +macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { + const SectionBase *Addr = + reinterpret_cast(Sections[DRI.d.a]); + macho::Section64 Ret; + memcpy(&Ret, Addr, sizeof(macho::Section64)); + if (isSwappedEndian(this)) + SwapStruct(Ret); + return Ret; +} + +macho::SymbolTableEntry +MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { + const char *P = getSymbolTableEntryPtr(this, DRI); + macho::SymbolTableEntry Ret; + memcpy(&Ret, P, sizeof(macho::SymbolTableEntry)); + if (isSwappedEndian(this)) + SwapStruct(Ret); + return Ret; +} + +macho::Symbol64TableEntry +MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { + const char *P = getSymbolTableEntryPtr(this, DRI); + macho::Symbol64TableEntry Ret; + memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry)); + if (isSwappedEndian(this)) + SwapStruct(Ret); + return Ret; +} + +macho::LinkeditDataLoadCommand +MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const { + macho::LinkeditDataLoadCommand Cmd; + memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand)); + if (isSwappedEndian(this)) + SwapStruct(Cmd); + return Cmd; +} + +macho::RelocationEntry +MachOObjectFile::getRelocation(DataRefImpl Rel) const { + uint32_t RelOffset; + DataRefImpl Sec; + Sec.d.a = Rel.d.b; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + RelOffset = Sect.RelocationTableOffset; + } else { + macho::Section Sect = getSection(Sec); + RelOffset = Sect.RelocationTableOffset; + } + + uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); + + macho::RelocationEntry Ret; + memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry)); + if (isSwappedEndian(this)) + SwapStruct(Ret); + + return Ret; +} + +macho::Header MachOObjectFile::getHeader() const { + macho::Header H; + memcpy(&H, getPtr(this, 0), sizeof(macho::Header)); + if (isSwappedEndian(this)) + SwapStruct(H); + return H; +} + +macho::SymtabLoadCommand +MachOObjectFile::getSymtabLoadCommand() const { + macho::SymtabLoadCommand Cmd; + memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand)); + if (isSwappedEndian(this)) + SwapStruct(Cmd); + return Cmd; +} + +bool MachOObjectFile::is64Bit() const { + return getType() == getMachOType(false, true) || + getType() == getMachOType(true, true); +} + +void MachOObjectFile::ReadULEB128s(uint64_t Index, + SmallVectorImpl &Out) const { + DataExtractor extractor(ObjectFile::getData(), true, 0); + + uint32_t offset = Index; + uint64_t data = 0; + while (uint64_t delta = extractor.getULEB128(&offset)) { + data += delta; + Out.push_back(data); + } +} + +ObjectFile *ObjectFile::createMachOObjectFile(MemoryBuffer *Buffer) { + StringRef Magic = Buffer->getBuffer().slice(0, 4); + error_code ec; + ObjectFile *Ret; + if (Magic == "\xFE\xED\xFA\xCE") + Ret = new MachOObjectFile(Buffer, false, false, ec); + else if (Magic == "\xCE\xFA\xED\xFE") + Ret = new MachOObjectFile(Buffer, true, false, ec); + else if (Magic == "\xFE\xED\xFA\xCF") + Ret = new MachOObjectFile(Buffer, false, true, ec); + else if (Magic == "\xCF\xFA\xED\xFE") + Ret = new MachOObjectFile(Buffer, true, true, ec); + else + return NULL; + + if (ec) + return NULL; + return Ret; +} + } // end namespace object } // end namespace llvm diff --git a/test/tools/llvm-readobj/Inputs/trivial.obj.macho-arm b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-arm new file mode 100644 index 0000000000..117df9efc1 Binary files /dev/null and b/test/tools/llvm-readobj/Inputs/trivial.obj.macho-arm differ diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index 6dc08eeb06..c23a7fe5bb 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -10,6 +10,8 @@ RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc \ RUN: | FileCheck %s -check-prefix MACHO-PPC RUN: llvm-readobj -r %p/Inputs/trivial.obj.macho-ppc64 \ RUN: | FileCheck %s -check-prefix MACHO-PPC64 +RUN: llvm-readobj -r -expand-relocs %p/Inputs/trivial.obj.macho-arm \ +RUN: | FileCheck %s -check-prefix MACHO-ARM COFF: Relocations [ COFF-NEXT: Section (1) .text { @@ -82,3 +84,90 @@ MACHO-PPC64-NEXT: Section __la_symbol_ptr { MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper MACHO-PPC64-NEXT: } MACHO-PPC64-NEXT: ] + + +MACHO-ARM: Relocations [ +MACHO-ARM-NEXT: Section __text { +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x38 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x20 +MACHO-ARM-NEXT: PCRel: 1 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_BR24 (5) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x1C +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 1 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 1 +MACHO-ARM-NEXT: Extern: 0 +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x18 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 0 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 0 +MACHO-ARM-NEXT: Extern: 0 +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0xC +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: ] diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index 3e42ab94fe..526ddfe82c 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -10,6 +10,8 @@ RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc \ RUN: | FileCheck %s -check-prefix MACHO-PPC RUN: llvm-readobj -s -st -sr -sd %p/Inputs/trivial.obj.macho-ppc64 \ RUN: | FileCheck %s -check-prefix MACHO-PPC64 +RUN: llvm-readobj -expand-relocs -s -st -sr -sd %p/Inputs/trivial.obj.macho-arm \ +RUN: | FileCheck %s -check-prefix MACHO-ARM COFF: Sections [ COFF-NEXT: Section { @@ -562,3 +564,278 @@ MACHO-PPC64-NEXT: 0000: 00000000 00000000 |........| MACHO-PPC64-NEXT: ) MACHO-PPC64-NEXT: } MACHO-PPC64-NEXT: ] + +MACHO-ARM: Sections [ +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 0 +MACHO-ARM-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x0 +MACHO-ARM-NEXT: Size: 0x3C +MACHO-ARM-NEXT: Offset: 664 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x2E0 +MACHO-ARM-NEXT: RelocationCount: 9 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x800004) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: SomeInstructions (0x4) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x38 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x20 +MACHO-ARM-NEXT: PCRel: 1 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_BR24 (5) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x1C +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 1 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 1 +MACHO-ARM-NEXT: Extern: 0 +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x18 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 0 +MACHO-ARM-NEXT: Extern: 1 +MACHO-ARM-NEXT: Type: ARM_RELOC_HALF (8) +MACHO-ARM-NEXT: Symbol: _g +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 0 +MACHO-ARM-NEXT: Extern: 0 +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0xC +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Relocation { +MACHO-ARM-NEXT: Offset: 0x0 +MACHO-ARM-NEXT: PCRel: 0 +MACHO-ARM-NEXT: Length: 2 +MACHO-ARM-NEXT: Extern: N/A +MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) +MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Scattered: 1 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: Symbol { +MACHO-ARM-NEXT: Name: _f (4) +MACHO-ARM-NEXT: Type: 0xF +MACHO-ARM-NEXT: Section: __text (0x1) +MACHO-ARM-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-ARM-NEXT: Flags [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Value: 0x10 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Symbol { +MACHO-ARM-NEXT: Name: _h (1) +MACHO-ARM-NEXT: Type: 0xF +MACHO-ARM-NEXT: Section: __text (0x1) +MACHO-ARM-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-ARM-NEXT: Flags [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Value: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: 0000: 04009FE5 00009FE7 1EFF2FE1 38000000 |........../.8...| +MACHO-ARM-NEXT: 0010: 80402DE9 0D70A0E1 000000E3 000040E3 |.@-..p........@.| +MACHO-ARM-NEXT: 0020: F6FFFFEB 0C009FE5 00009FE7 000090E5 |................| +MACHO-ARM-NEXT: 0030: 8040BDE8 1EFF2FE1 10000000 |.@..../.....| +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 1 +MACHO-ARM-NEXT: Name: __textcoal_nt (5F 5F 74 65 78 74 63 6F 61 6C 5F 6E 74 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0xB +MACHO-ARM-NEXT: Attributes [ (0x800000) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 2 +MACHO-ARM-NEXT: Name: __const_coal (5F 5F 63 6F 6E 73 74 5F 63 6F 61 6C 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0xB +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 3 +MACHO-ARM-NEXT: Name: __picsymbolstub4 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 34) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x8 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x10 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 4 +MACHO-ARM-NEXT: Name: __StaticInit (5F 5F 53 74 61 74 69 63 49 6E 69 74 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x800000) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 5 +MACHO-ARM-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x4 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: Symbol { +MACHO-ARM-NEXT: Name: _b (10) +MACHO-ARM-NEXT: Type: 0xF +MACHO-ARM-NEXT: Section: __data (0x6) +MACHO-ARM-NEXT: RefType: UndefinedNonLazy (0x0) +MACHO-ARM-NEXT: Flags [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Value: 0x3C +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: 0000: 2A000000 |*...| +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 6 +MACHO-ARM-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-ARM-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x40 +MACHO-ARM-NEXT: Size: 0x8 +MACHO-ARM-NEXT: Offset: 728 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x6 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: Relocations [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Symbols [ +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: SectionData ( +MACHO-ARM-NEXT: 0000: 00000000 00000000 |........| +MACHO-ARM-NEXT: ) +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: ] diff --git a/test/tools/llvm-readobj/sections.test b/test/tools/llvm-readobj/sections.test index b569682497..16f1131e05 100644 --- a/test/tools/llvm-readobj/sections.test +++ b/test/tools/llvm-readobj/sections.test @@ -10,6 +10,8 @@ RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc \ RUN: | FileCheck %s -check-prefix MACHO-PPC RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-ppc64 \ RUN: | FileCheck %s -check-prefix MACHO-PPC64 +RUN: llvm-readobj -s %p/Inputs/trivial.obj.macho-arm \ +RUN: | FileCheck %s -check-prefix MACHO-ARM COFF: Sections [ COFF-NEXT: Section { @@ -329,3 +331,122 @@ MACHO-PPC64-NEXT: Reserved1: 0x2 MACHO-PPC64-NEXT: Reserved2: 0x0 MACHO-PPC64-NEXT: } MACHO-PPC64-NEXT: ] + +MACHO-ARM: Sections [ +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 0 +MACHO-ARM-NEXT: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x0 +MACHO-ARM-NEXT: Size: 0x3C +MACHO-ARM-NEXT: Offset: 664 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x2E0 +MACHO-ARM-NEXT: RelocationCount: 9 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x800004) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: SomeInstructions (0x4) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 1 +MACHO-ARM-NEXT: Name: __textcoal_nt (5F 5F 74 65 78 74 63 6F 61 6C 5F 6E 74 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0xB +MACHO-ARM-NEXT: Attributes [ (0x800000) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 2 +MACHO-ARM-NEXT: Name: __const_coal (5F 5F 63 6F 6E 73 74 5F 63 6F 61 6C 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0xB +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 3 +MACHO-ARM-NEXT: Name: __picsymbolstub4 (5F 5F 70 69 63 73 79 6D 62 6F 6C 73 74 75 62 34) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x8 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x10 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 4 +MACHO-ARM-NEXT: Name: __StaticInit (5F 5F 53 74 61 74 69 63 49 6E 69 74 00 00 00 00) +MACHO-ARM-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x0 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 0 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x800000) +MACHO-ARM-NEXT: PureInstructions (0x800000) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 5 +MACHO-ARM-NEXT: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x3C +MACHO-ARM-NEXT: Size: 0x4 +MACHO-ARM-NEXT: Offset: 724 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x0 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT: Section { +MACHO-ARM-NEXT: Index: 6 +MACHO-ARM-NEXT: Name: __nl_symbol_ptr (5F 5F 6E 6C 5F 73 79 6D 62 6F 6C 5F 70 74 72 00) +MACHO-ARM-NEXT: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00) +MACHO-ARM-NEXT: Address: 0x40 +MACHO-ARM-NEXT: Size: 0x8 +MACHO-ARM-NEXT: Offset: 728 +MACHO-ARM-NEXT: Alignment: 2 +MACHO-ARM-NEXT: RelocationOffset: 0x0 +MACHO-ARM-NEXT: RelocationCount: 0 +MACHO-ARM-NEXT: Type: 0x6 +MACHO-ARM-NEXT: Attributes [ (0x0) +MACHO-ARM-NEXT: ] +MACHO-ARM-NEXT: Reserved1: 0x0 +MACHO-ARM-NEXT: Reserved2: 0x0 +MACHO-ARM-NEXT: } +MACHO-ARM-NEXT:] diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index 4b6cb5f54c..e4d9ce2498 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -53,7 +53,7 @@ static cl::opt static cl::opt DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObjectFileBase *MachOObj) { +static const Target *GetTarget(const MachOObjectFile *MachOObj) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); @@ -93,7 +93,7 @@ struct SymbolSorter { // Print additional information about an address, if available. static void DumpAddress(uint64_t Address, ArrayRef Sections, - const MachOObjectFileBase *MachOObj, raw_ostream &OS) { + const MachOObjectFile *MachOObj, raw_ostream &OS) { for (unsigned i = 0; i != Sections.size(); ++i) { uint64_t SectAddr = 0, SectSize = 0; Sections[i].getAddress(SectAddr); @@ -184,14 +184,12 @@ static void emitDOTFile(const char *FileName, const MCFunction &f, Out << "}\n"; } -template static void -getSectionsAndSymbols(const typename MachOObjectFileMiddle::Header *Header, - const MachOObjectFileMiddle *MachOObj, +getSectionsAndSymbols(const macho::Header Header, + MachOObjectFile *MachOObj, std::vector &Sections, std::vector &Symbols, SmallVectorImpl &FoundFns) { - typedef MachOObjectFileMiddle ObjType; error_code ec; for (symbol_iterator SI = MachOObj->begin_symbols(), SE = MachOObj->end_symbols(); SI != SE; SI.increment(ec)) @@ -205,23 +203,23 @@ getSectionsAndSymbols(const typename MachOObjectFileMiddle::Header *Header, Sections.push_back(*SI); } - for (unsigned i = 0; i != Header->NumLoadCommands; ++i) { - const typename ObjType::LoadCommand *Command = - MachOObj->getLoadCommandInfo(i); - if (Command->Type == macho::LCT_FunctionStarts) { + MachOObjectFile::LoadCommandInfo Command = + MachOObj->getFirstLoadCommandInfo(); + for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + if (Command.C.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. - const typename ObjType::LinkeditDataLoadCommand *LLC = - reinterpret_cast(Command); + macho::LinkeditDataLoadCommand LLC = + MachOObj->getLinkeditDataLoadCommand(Command); - MachOObj->ReadULEB128s(LLC->DataOffset, FoundFns); + MachOObj->ReadULEB128s(LLC.DataOffset, FoundFns); } + Command = MachOObj->getNextLoadCommandInfo(Command); } } -template static void DisassembleInputMachO2(StringRef Filename, - MachOObjectFileMiddle *MachOOF); + MachOObjectFile *MachOOF); void llvm::DisassembleInputMachO(StringRef Filename) { OwningPtr Buff; @@ -231,20 +229,14 @@ void llvm::DisassembleInputMachO(StringRef Filename) { return; } - OwningPtr MachOOF(static_cast( + OwningPtr MachOOF(static_cast( ObjectFile::createMachOObjectFile(Buff.take()))); - if (MachOObjectFileLE *O = dyn_cast(MachOOF.get())) { - DisassembleInputMachO2(Filename, O); - return; - } - MachOObjectFileBE *O = cast(MachOOF.get()); - DisassembleInputMachO2(Filename, O); + DisassembleInputMachO2(Filename, MachOOF.get()); } -template static void DisassembleInputMachO2(StringRef Filename, - MachOObjectFileMiddle *MachOOF) { + MachOObjectFile *MachOOF) { const Target *TheTarget = GetTarget(MachOOF); if (!TheTarget) { // GetTarget prints out stuff. @@ -273,8 +265,7 @@ static void DisassembleInputMachO2(StringRef Filename, outs() << '\n' << Filename << ":\n\n"; - const typename MachOObjectFileMiddle::Header *Header = - MachOOF->getHeader(); + macho::Header Header = MachOOF->getHeader(); std::vector Sections; std::vector Symbols; diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 6f4b101c30..9985599565 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -191,14 +191,6 @@ bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { return a_addr < b_addr; } -StringRef -getSectionFinalSegmentName(const MachOObjectFileBase *MachO, DataRefImpl DR) { - if (const MachOObjectFileLE *O = dyn_cast(MachO)) - return O->getSectionFinalSegmentName(DR); - const MachOObjectFileBE *O = dyn_cast(MachO); - return O->getSectionFinalSegmentName(DR); -} - static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { const Target *TheTarget = getTarget(Obj); // getTarget() will have already issued a diagnostic if necessary, so @@ -263,10 +255,10 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::sort(Rels.begin(), Rels.end(), RelocAddressLess); StringRef SegmentName = ""; - if (const MachOObjectFileBase *MachO = - dyn_cast(Obj)) { + if (const MachOObjectFile *MachO = + dyn_cast(Obj)) { DataRefImpl DR = i->getRawDataRefImpl(); - SegmentName = getSectionFinalSegmentName(MachO, DR); + SegmentName = MachO->getSectionFinalSegmentName(DR); } StringRef name; if (error(i->getName(name))) break; @@ -608,10 +600,10 @@ static void PrintSymbolTable(const ObjectFile *o) { else if (Section == o->end_sections()) outs() << "*UND*"; else { - if (const MachOObjectFileBase *MachO = - dyn_cast(o)) { + if (const MachOObjectFile *MachO = + dyn_cast(o)) { DataRefImpl DR = Section->getRawDataRefImpl(); - StringRef SegmentName = getSectionFinalSegmentName(MachO, DR); + StringRef SegmentName = MachO->getSectionFinalSegmentName(DR); outs() << SegmentName << ","; } StringRef SectionName; diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index d4eaae615c..54de49c310 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -27,7 +27,7 @@ namespace { class MachODumper : public ObjDumper { public: - MachODumper(const MachOObjectFileBase *Obj, StreamWriter& Writer) + MachODumper(const MachOObjectFile *Obj, StreamWriter& Writer) : ObjDumper(Writer) , Obj(Obj) { } @@ -43,14 +43,12 @@ private: void printRelocation(section_iterator SecI, relocation_iterator RelI); - template - void printRelocation(const MachOObjectFileMiddle *Obj, + void printRelocation(const MachOObjectFile *Obj, section_iterator SecI, relocation_iterator RelI); - template - void printSections(const MachOObjectFileMiddle *Obj); + void printSections(const MachOObjectFile *Obj); - const MachOObjectFileBase *Obj; + const MachOObjectFile *Obj; }; } // namespace @@ -61,7 +59,7 @@ namespace llvm { error_code createMachODumper(const object::ObjectFile *Obj, StreamWriter& Writer, OwningPtr &Result) { - const MachOObjectFileBase *MachOObj = dyn_cast(Obj); + const MachOObjectFile *MachOObj = dyn_cast(Obj); if (!MachOObj) return readobj_error::unsupported_obj_file_format; @@ -164,59 +162,53 @@ namespace { }; } -template -static void getSection(const MachOObjectFile *Obj, - DataRefImpl DRI, +static void getSection(const MachOObjectFile *Obj, + DataRefImpl Sec, MachOSection &Section) { - const typename MachOObjectFile::Section *Sect = Obj->getSection(DRI); - Section.Address = Sect->Address; - Section.Size = Sect->Size; - Section.Offset = Sect->Offset; - Section.Alignment = Sect->Align; - Section.RelocationTableOffset = Sect->RelocationTableOffset; - Section.NumRelocationTableEntries = Sect->NumRelocationTableEntries; - Section.Flags = Sect->Flags; - Section.Reserved1 = Sect->Reserved1; - Section.Reserved2 = Sect->Reserved2; -} - -static void getSection(const MachOObjectFileBase *Obj, - DataRefImpl DRI, - MachOSection &Section) { - if (const MachOObjectFileLE32 *O = dyn_cast(Obj)) - return getSection(O, DRI, Section); - if (const MachOObjectFileLE64 *O = dyn_cast(Obj)) - return getSection(O, DRI, Section); - if (const MachOObjectFileBE32 *O = dyn_cast(Obj)) - return getSection(O, DRI, Section); - const MachOObjectFileBE64 *O = cast(Obj); - getSection(O, DRI, Section); + if (!Obj->is64Bit()) { + macho::Section Sect = Obj->getSection(Sec); + Section.Address = Sect.Address; + Section.Size = Sect.Size; + Section.Offset = Sect.Offset; + Section.Alignment = Sect.Align; + Section.RelocationTableOffset = Sect.RelocationTableOffset; + Section.NumRelocationTableEntries = Sect.NumRelocationTableEntries; + Section.Flags = Sect.Flags; + Section.Reserved1 = Sect.Reserved1; + Section.Reserved2 = Sect.Reserved2; + return; + } + macho::Section64 Sect = Obj->getSection64(Sec); + Section.Address = Sect.Address; + Section.Size = Sect.Size; + Section.Offset = Sect.Offset; + Section.Alignment = Sect.Align; + Section.RelocationTableOffset = Sect.RelocationTableOffset; + Section.NumRelocationTableEntries = Sect.NumRelocationTableEntries; + Section.Flags = Sect.Flags; + Section.Reserved1 = Sect.Reserved1; + Section.Reserved2 = Sect.Reserved2; } -template -static void getSymbol(const MachOObjectFile *Obj, - DataRefImpl DRI, - MachOSymbol &Symbol) { - const typename MachOObjectFile::SymbolTableEntry *Entry = - Obj->getSymbolTableEntry(DRI); - Symbol.StringIndex = Entry->StringIndex; - Symbol.Type = Entry->Type; - Symbol.SectionIndex = Entry->SectionIndex; - Symbol.Flags = Entry->Flags; - Symbol.Value = Entry->Value; -} -static void getSymbol(const MachOObjectFileBase *Obj, +static void getSymbol(const MachOObjectFile *Obj, DataRefImpl DRI, MachOSymbol &Symbol) { - if (const MachOObjectFileLE32 *O = dyn_cast(Obj)) - return getSymbol(O, DRI, Symbol); - if (const MachOObjectFileLE64 *O = dyn_cast(Obj)) - return getSymbol(O, DRI, Symbol); - if (const MachOObjectFileBE32 *O = dyn_cast(Obj)) - return getSymbol(O, DRI, Symbol); - const MachOObjectFileBE64 *O = cast(Obj); - getSymbol(O, DRI, Symbol); + if (!Obj->is64Bit()) { + macho::SymbolTableEntry Entry = Obj->getSymbolTableEntry(DRI); + Symbol.StringIndex = Entry.StringIndex; + Symbol.Type = Entry.Type; + Symbol.SectionIndex = Entry.SectionIndex; + Symbol.Flags = Entry.Flags; + Symbol.Value = Entry.Value; + return; + } + macho::Symbol64TableEntry Entry = Obj->getSymbol64TableEntry(DRI); + Symbol.StringIndex = Entry.StringIndex; + Symbol.Type = Entry.Type; + Symbol.SectionIndex = Entry.SectionIndex; + Symbol.Flags = Entry.Flags; + Symbol.Value = Entry.Value; } void MachODumper::printFileHeaders() { @@ -224,14 +216,10 @@ void MachODumper::printFileHeaders() { } void MachODumper::printSections() { - if (const MachOObjectFileLE *O = dyn_cast(Obj)) - return printSections(O); - const MachOObjectFileBE *O = cast(Obj); - return printSections(O); + return printSections(Obj); } -template -void MachODumper::printSections(const MachOObjectFileMiddle *Obj) { +void MachODumper::printSections(const MachOObjectFile *Obj) { ListScope Group(W, "Sections"); int SectionIndex = -1; @@ -344,14 +332,10 @@ void MachODumper::printRelocations() { void MachODumper::printRelocation(section_iterator SecI, relocation_iterator RelI) { - if (const MachOObjectFileLE *O = dyn_cast(Obj)) - return printRelocation(O, SecI, RelI); - const MachOObjectFileBE *O = cast(Obj); - return printRelocation(O, SecI, RelI); + return printRelocation(Obj, SecI, RelI); } -template -void MachODumper::printRelocation(const MachOObjectFileMiddle *Obj, +void MachODumper::printRelocation(const MachOObjectFile *Obj, section_iterator SecI, relocation_iterator RelI) { uint64_t Offset; @@ -364,31 +348,30 @@ void MachODumper::printRelocation(const MachOObjectFileMiddle *Obj, if (error(Symbol.getName(SymbolName))) return; DataRefImpl DR = RelI->getRawDataRefImpl(); - const typename MachOObjectFileMiddle::RelocationEntry *RE = - Obj->getRelocation(DR); + macho::RelocationEntry RE = Obj->getRelocation(DR); bool IsScattered = Obj->isRelocationScattered(RE); if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); - W.printNumber("PCRel", Obj->isRelocationPCRel(RE)); - W.printNumber("Length", Obj->getRelocationLength(RE)); + W.printNumber("PCRel", Obj->getAnyRelocationPCRel(RE)); + W.printNumber("Length", Obj->getAnyRelocationLength(RE)); if (IsScattered) W.printString("Extern", StringRef("N/A")); else - W.printNumber("Extern", RE->External); - W.printNumber("Type", RelocName, RE->Type); + W.printNumber("Extern", Obj->getPlainRelocationExternal(RE)); + W.printNumber("Type", RelocName, Obj->getAnyRelocationType(RE)); W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); W.printNumber("Scattered", IsScattered); } else { raw_ostream& OS = W.startLine(); OS << W.hex(Offset) - << " " << Obj->isRelocationPCRel(RE) - << " " << Obj->getRelocationLength(RE); + << " " << Obj->getAnyRelocationPCRel(RE) + << " " << Obj->getAnyRelocationLength(RE); if (IsScattered) OS << " n/a"; else - OS << " " << RE->External; + OS << " " << Obj->getPlainRelocationExternal(RE); OS << " " << RelocName << " " << IsScattered << " " << (SymbolName.size() > 0 ? SymbolName : "-") diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index ffe8712a65..29d91a0e92 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -233,7 +233,7 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { // On Darwin we may find DWARF in separate object file in // resource directory. ObjectFile *DbgObj = Obj; - if (isa(Obj)) { + if (isa(Obj)) { const std::string &ResourceName = getDarwinDWARFResourceForModule(ModuleName); ObjectFile *ResourceObj = getObjectFile(ResourceName); -- cgit v1.2.3-70-g09d2 From db5f9270207292b62ea847560c5dd4e9873b57f5 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 19 Apr 2013 11:36:47 +0000 Subject: Don't read one command past the end. Thanks to Evgeniy Stepanov for reporting this. It might be a good idea to add a command iterator abstraction to MachO.h, but this fixes the bug for now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179848 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 8 ++++++-- test/Object/ARM/objdump-thumb.test | 4 ++++ test/Object/Inputs/macho-text.thumb | Bin 0 -> 156 bytes tools/llvm-objdump/MachODump.cpp | 8 ++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 test/Object/ARM/objdump-thumb.test create mode 100644 test/Object/Inputs/macho-text.thumb (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index f5910dd95d..d26eb2ce61 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -405,7 +405,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, macho::LCT_Segment64 : macho::LCT_Segment; MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); - for (unsigned I = 0; I < LoadCommandCount; ++I) { + for (unsigned I = 0; ; ++I) { if (Load.C.Type == macho::LCT_Symtab) { assert(!SymtabLoadCmd && "Multiple symbol tables"); SymtabLoadCmd = Load.Ptr; @@ -418,7 +418,11 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, Sections.push_back(reinterpret_cast(Sec)); } } - Load = getNextLoadCommandInfo(Load); + + if (I == LoadCommandCount - 1) + break; + else + Load = getNextLoadCommandInfo(Load); } } diff --git a/test/Object/ARM/objdump-thumb.test b/test/Object/ARM/objdump-thumb.test new file mode 100644 index 0000000000..9c92a27782 --- /dev/null +++ b/test/Object/ARM/objdump-thumb.test @@ -0,0 +1,4 @@ +RUN: llvm-objdump -d -macho -triple=thumbv7-apple-ios \ +RUN: %p/../Inputs/macho-text.thumb | FileCheck %s + +CHECK: 0: 00 bf nop diff --git a/test/Object/Inputs/macho-text.thumb b/test/Object/Inputs/macho-text.thumb new file mode 100644 index 0000000000..b29428a787 Binary files /dev/null and b/test/Object/Inputs/macho-text.thumb differ diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index e4d9ce2498..d78d7f31a6 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -205,7 +205,7 @@ getSectionsAndSymbols(const macho::Header Header, MachOObjectFile::LoadCommandInfo Command = MachOObj->getFirstLoadCommandInfo(); - for (unsigned i = 0; i != Header.NumLoadCommands; ++i) { + for (unsigned i = 0; ; ++i) { if (Command.C.Type == macho::LCT_FunctionStarts) { // We found a function starts segment, parse the addresses for later // consumption. @@ -214,7 +214,11 @@ getSectionsAndSymbols(const macho::Header Header, MachOObj->ReadULEB128s(LLC.DataOffset, FoundFns); } - Command = MachOObj->getNextLoadCommandInfo(Command); + + if (i == Header.NumLoadCommands - 1) + break; + else + Command = MachOObj->getNextLoadCommandInfo(Command); } } -- cgit v1.2.3-70-g09d2 From 143d223447cb55ae08d313078f7a5917873247ae Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 19 Apr 2013 13:45:05 +0000 Subject: refactor the struct byte swapping to a helper function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179851 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 90 ++++++++++-------------------------------- 1 file changed, 20 insertions(+), 70 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index d26eb2ce61..2f5048688c 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -165,28 +165,25 @@ void SwapStruct(macho::Segment64LoadCommand &C) { SwapValue(C.Flags); } -static bool isSwappedEndian(const MachOObjectFile *O) { - return O->isLittleEndian() != sys::IsLittleEndianHost; +template +T getStruct(const MachOObjectFile *O, const char *P) { + T Cmd; + memcpy(&Cmd, P, sizeof(T)); + if (O->isLittleEndian() != sys::IsLittleEndianHost) + SwapStruct(Cmd); + return Cmd; } static macho::SegmentLoadCommand getSegmentLoadCommand(const MachOObjectFile *O, const MachOObjectFile::LoadCommandInfo &L) { - macho::SegmentLoadCommand Cmd; - memcpy(&Cmd, L.Ptr, sizeof(macho::SegmentLoadCommand)); - if (isSwappedEndian(O)) - SwapStruct(Cmd); - return Cmd; + return getStruct(O, L.Ptr); } static macho::Segment64LoadCommand getSegment64LoadCommand(const MachOObjectFile *O, const MachOObjectFile::LoadCommandInfo &L) { - macho::Segment64LoadCommand Cmd; - memcpy(&Cmd, L.Ptr, sizeof(macho::Segment64LoadCommand)); - if (isSwappedEndian(O)) - SwapStruct(Cmd); - return Cmd; + return getStruct(O, L.Ptr); } static uint32_t @@ -236,12 +233,7 @@ static const char *getSymbolTableEntryPtr(const MachOObjectFile *O, static SymbolTableEntryBase getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { const char *P = getSymbolTableEntryPtr(O, DRI); - SymbolTableEntryBase Ret; - memcpy(&Ret, P, sizeof(SymbolTableEntryBase)); - if (isSwappedEndian(O)) - SwapStruct(Ret); - - return Ret; + return getStruct(O, P); } static StringRef parseSegmentOrSectionName(const char *P) { @@ -1366,9 +1358,7 @@ MachOObjectFile::getFirstLoadCommandInfo() const { unsigned HeaderSize = is64Bit() ? macho::Header64Size : macho::Header32Size; Load.Ptr = getPtr(this, HeaderSize); - memcpy(&Load.C, Load.Ptr, sizeof(macho::LoadCommand)); - if (isSwappedEndian(this)) - SwapStruct(Load.C); + Load.C = getStruct(this, Load.Ptr); return Load; } @@ -1376,59 +1366,33 @@ MachOObjectFile::LoadCommandInfo MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { MachOObjectFile::LoadCommandInfo Next; Next.Ptr = L.Ptr + L.C.Size; - memcpy(&Next.C, Next.Ptr, sizeof(macho::LoadCommand)); - if (isSwappedEndian(this)) - SwapStruct(Next.C); + Next.C = getStruct(this, Next.Ptr); return Next; } macho::Section MachOObjectFile::getSection(DataRefImpl DRI) const { - const SectionBase *Addr = - reinterpret_cast(Sections[DRI.d.a]); - macho::Section Ret; - memcpy(&Ret, Addr, sizeof(macho::Section)); - if (isSwappedEndian(this)) - SwapStruct(Ret); - return Ret; + return getStruct(this, Sections[DRI.d.a]); } macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { - const SectionBase *Addr = - reinterpret_cast(Sections[DRI.d.a]); - macho::Section64 Ret; - memcpy(&Ret, Addr, sizeof(macho::Section64)); - if (isSwappedEndian(this)) - SwapStruct(Ret); - return Ret; + return getStruct(this, Sections[DRI.d.a]); } macho::SymbolTableEntry MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { const char *P = getSymbolTableEntryPtr(this, DRI); - macho::SymbolTableEntry Ret; - memcpy(&Ret, P, sizeof(macho::SymbolTableEntry)); - if (isSwappedEndian(this)) - SwapStruct(Ret); - return Ret; + return getStruct(this, P); } macho::Symbol64TableEntry MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { const char *P = getSymbolTableEntryPtr(this, DRI); - macho::Symbol64TableEntry Ret; - memcpy(&Ret, P, sizeof(macho::Symbol64TableEntry)); - if (isSwappedEndian(this)) - SwapStruct(Ret); - return Ret; + return getStruct(this, P); } macho::LinkeditDataLoadCommand MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandInfo &L) const { - macho::LinkeditDataLoadCommand Cmd; - memcpy(&Cmd, L.Ptr, sizeof(macho::LinkeditDataLoadCommand)); - if (isSwappedEndian(this)) - SwapStruct(Cmd); - return Cmd; + return getStruct(this, L.Ptr); } macho::RelocationEntry @@ -1445,30 +1409,16 @@ MachOObjectFile::getRelocation(DataRefImpl Rel) const { } uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); - - macho::RelocationEntry Ret; - memcpy(&Ret, getPtr(this, Offset), sizeof(macho::RelocationEntry)); - if (isSwappedEndian(this)) - SwapStruct(Ret); - - return Ret; + return getStruct(this, getPtr(this, Offset)); } macho::Header MachOObjectFile::getHeader() const { - macho::Header H; - memcpy(&H, getPtr(this, 0), sizeof(macho::Header)); - if (isSwappedEndian(this)) - SwapStruct(H); - return H; + return getStruct(this, getPtr(this, 0)); } macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const { - macho::SymtabLoadCommand Cmd; - memcpy(&Cmd, SymtabLoadCmd, sizeof(macho::SymtabLoadCommand)); - if (isSwappedEndian(this)) - SwapStruct(Cmd); - return Cmd; + return getStruct(this, SymtabLoadCmd); } bool MachOObjectFile::is64Bit() const { -- cgit v1.2.3-70-g09d2 From 709d2fdb11a623ab2dd3b0a3754d09ad0f91b7e2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 24 Apr 2013 15:02:03 +0000 Subject: Use a pointer as the relocation iterator. Since the relocation iterator walks only the relocations in one section, we can just use a pointer and avoid fetching information about the section at every reference. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180189 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 51 +++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 23 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 2f5048688c..08570f1314 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -777,31 +777,47 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, } relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl ret; - ret.d.b = Sec.d.a; - return relocation_iterator(RelocationRef(ret, this)); + uint32_t Offset; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Offset = Sect.RelocationTableOffset; + } else { + macho::Section Sect = getSection(Sec); + Offset = Sect.RelocationTableOffset; + } + + DataRefImpl Ret; + Ret.p = reinterpret_cast(getPtr(this, Offset)); + return relocation_iterator(RelocationRef(Ret, this)); } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - uint32_t LastReloc; + uint32_t Offset; + uint32_t Num; if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); - LastReloc = Sect.NumRelocationTableEntries; + Offset = Sect.RelocationTableOffset; + Num = Sect.NumRelocationTableEntries; } else { macho::Section Sect = getSection(Sec); - LastReloc = Sect.NumRelocationTableEntries; + Offset = Sect.RelocationTableOffset; + Num = Sect.NumRelocationTableEntries; } + const macho::RelocationEntry *P = + reinterpret_cast(getPtr(this, Offset)); + DataRefImpl Ret; - Ret.d.a = LastReloc; - Ret.d.b = Sec.d.a; + Ret.p = reinterpret_cast(P + Num); return relocation_iterator(RelocationRef(Ret, this)); } error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { - ++Rel.d.a; + RelocationRef &Res) const { + const macho::RelocationEntry *P = + reinterpret_cast(Rel.p); + Rel.p = reinterpret_cast(P + 1); Res = RelocationRef(Rel, this); return object_error::success; } @@ -1397,19 +1413,8 @@ MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandIn macho::RelocationEntry MachOObjectFile::getRelocation(DataRefImpl Rel) const { - uint32_t RelOffset; - DataRefImpl Sec; - Sec.d.a = Rel.d.b; - if (is64Bit()) { - macho::Section64 Sect = getSection64(Sec); - RelOffset = Sect.RelocationTableOffset; - } else { - macho::Section Sect = getSection(Sec); - RelOffset = Sect.RelocationTableOffset; - } - - uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); - return getStruct(this, getPtr(this, Offset)); + const char *P = reinterpret_cast(Rel.p); + return getStruct(this, P); } macho::Header MachOObjectFile::getHeader() const { -- cgit v1.2.3-70-g09d2 From f69a81f001613b834960bae69cd6099265cc4d98 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 24 Apr 2013 15:14:22 +0000 Subject: Formatting fixes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180190 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 51 +++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 08570f1314..e4b3350843 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -615,7 +615,7 @@ MachOObjectFile::getSymbolSection(DataRefImpl Symb, } error_code MachOObjectFile::getSymbolValue(DataRefImpl Symb, - uint64_t &Val) const { + uint64_t &Val) const { report_fatal_error("getSymbolValue unimplemented in MachOObjectFile"); } @@ -627,16 +627,14 @@ error_code MachOObjectFile::getSectionNext(DataRefImpl Sec, } error_code -MachOObjectFile::getSectionName(DataRefImpl Sec, - StringRef &Result) const { +MachOObjectFile::getSectionName(DataRefImpl Sec, StringRef &Result) const { ArrayRef Raw = getSectionRawName(Sec); Result = parseSegmentOrSectionName(Raw.data()); return object_error::success; } error_code -MachOObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionAddress(DataRefImpl Sec, uint64_t &Res) const { if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); Res = Sect.Address; @@ -648,8 +646,7 @@ MachOObjectFile::getSectionAddress(DataRefImpl Sec, } error_code -MachOObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionSize(DataRefImpl Sec, uint64_t &Res) const { if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); Res = Sect.Size; @@ -662,8 +659,7 @@ MachOObjectFile::getSectionSize(DataRefImpl Sec, } error_code -MachOObjectFile::getSectionContents(DataRefImpl Sec, - StringRef &Res) const { +MachOObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Res) const { uint32_t Offset; uint64_t Size; @@ -682,8 +678,7 @@ MachOObjectFile::getSectionContents(DataRefImpl Sec, } error_code -MachOObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const { +MachOObjectFile::getSectionAlignment(DataRefImpl Sec, uint64_t &Res) const { uint32_t Align; if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); @@ -704,15 +699,13 @@ MachOObjectFile::isSectionText(DataRefImpl Sec, bool &Res) const { return object_error::success; } -error_code MachOObjectFile::isSectionData(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFile::isSectionData(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; } -error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, - bool &Result) const { +error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; @@ -720,14 +713,14 @@ error_code MachOObjectFile::isSectionBSS(DataRefImpl DRI, error_code MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { + bool &Result) const { // FIXME: Unimplemented. Result = true; return object_error::success; } error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { + bool &Result) const { // FIXME: Unimplemented. Result = false; return object_error::success; @@ -743,7 +736,7 @@ MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, bool &Res) const { } error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { + bool &Result) const { // Consider using the code from isSectionText to look for __const sections. // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS // to use section attributes to distinguish code from data. @@ -754,8 +747,7 @@ error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, } error_code -MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, +MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, bool &Result) const { SymbolRef::Type ST; this->getSymbolType(Symb, ST); @@ -823,8 +815,7 @@ error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, } error_code -MachOObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const { +MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { uint64_t SectAddress; DataRefImpl Sec; Sec.d.a = Rel.d.b; @@ -843,15 +834,14 @@ MachOObjectFile::getRelocationAddress(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const { + uint64_t &Res) const { macho::RelocationEntry RE = getRelocation(Rel); Res = getAnyRelocationAddress(RE); return object_error::success; } error_code -MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, - SymbolRef &Res) const { +MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { macho::RelocationEntry RE = getRelocation(Rel); uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); bool isExtern = getPlainRelocationExternal(RE); @@ -865,7 +855,7 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, } error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Res) const { + uint64_t &Res) const { macho::RelocationEntry RE = getRelocation(Rel); Res = getAnyRelocationType(RE); return object_error::success; @@ -972,7 +962,7 @@ error_code MachOObjectFile::getRelocationAdditionalInfo(DataRefImpl Rel, error_code MachOObjectFile::getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const { + SmallVectorImpl &Result) const { macho::RelocationEntry RE = getRelocation(Rel); unsigned Arch = this->getArch(); @@ -1148,8 +1138,7 @@ MachOObjectFile::getRelocationValueString(DataRefImpl Rel, } error_code -MachOObjectFile::getRelocationHidden(DataRefImpl Rel, - bool &Result) const { +MachOObjectFile::getRelocationHidden(DataRefImpl Rel, bool &Result) const { unsigned Arch = getArch(); uint64_t Type; getRelocationType(Rel, Type); @@ -1177,12 +1166,12 @@ MachOObjectFile::getRelocationHidden(DataRefImpl Rel, } error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { + LibraryRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { + StringRef &Res) const { report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); } -- cgit v1.2.3-70-g09d2 From 51cc82887cdd6795caaffc0ece500481b697bced Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 24 Apr 2013 16:10:49 +0000 Subject: Revert r180189. This should bring the ppc bots back. I will try to write a test that would have found the problem on a little endian system too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180194 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 53 +++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 29 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index e4b3350843..4e6e0bdada 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -769,47 +769,31 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, } relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { - uint32_t Offset; - if (is64Bit()) { - macho::Section64 Sect = getSection64(Sec); - Offset = Sect.RelocationTableOffset; - } else { - macho::Section Sect = getSection(Sec); - Offset = Sect.RelocationTableOffset; - } - - DataRefImpl Ret; - Ret.p = reinterpret_cast(getPtr(this, Offset)); - return relocation_iterator(RelocationRef(Ret, this)); + DataRefImpl ret; + ret.d.b = Sec.d.a; + return relocation_iterator(RelocationRef(ret, this)); } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - uint32_t Offset; - uint32_t Num; + uint32_t LastReloc; if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); - Offset = Sect.RelocationTableOffset; - Num = Sect.NumRelocationTableEntries; + LastReloc = Sect.NumRelocationTableEntries; } else { macho::Section Sect = getSection(Sec); - Offset = Sect.RelocationTableOffset; - Num = Sect.NumRelocationTableEntries; + LastReloc = Sect.NumRelocationTableEntries; } - const macho::RelocationEntry *P = - reinterpret_cast(getPtr(this, Offset)); - DataRefImpl Ret; - Ret.p = reinterpret_cast(P + Num); + Ret.d.a = LastReloc; + Ret.d.b = Sec.d.a; return relocation_iterator(RelocationRef(Ret, this)); } -error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { - const macho::RelocationEntry *P = - reinterpret_cast(Rel.p); - Rel.p = reinterpret_cast(P + 1); + error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + ++Rel.d.a; Res = RelocationRef(Rel, this); return object_error::success; } @@ -1402,8 +1386,19 @@ MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandIn macho::RelocationEntry MachOObjectFile::getRelocation(DataRefImpl Rel) const { - const char *P = reinterpret_cast(Rel.p); - return getStruct(this, P); + uint32_t RelOffset; + DataRefImpl Sec; + Sec.d.a = Rel.d.b; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + RelOffset = Sect.RelocationTableOffset; + } else { + macho::Section Sect = getSection(Sec); + RelOffset = Sect.RelocationTableOffset; + } + + uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); + return getStruct(this, getPtr(this, Offset)); } macho::Header MachOObjectFile::getHeader() const { -- cgit v1.2.3-70-g09d2 From 802fe9340d032d20195b00334356cf63b303386c Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 24 Apr 2013 19:47:55 +0000 Subject: Use pointers to iterate over symbols. While here, don't report a dummy symbol for relocations that don't have symbols. We used to says such relocations were for the first defined symbol, but now we return end_symbols(). The llvm-readobj output change agrees with otool. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180214 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 66 +++++++++++++++++-------------- test/tools/llvm-readobj/relocations.test | 52 ++++++++++++------------ test/tools/llvm-readobj/sections-ext.test | 52 ++++++++++++------------ tools/llvm-readobj/MachODumper.cpp | 4 +- 4 files changed, 91 insertions(+), 83 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 4e6e0bdada..51cd5b9a95 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -216,23 +216,9 @@ static const char *getPtr(const MachOObjectFile *O, size_t Offset) { return O->getData().substr(Offset, 1).data(); } -static const char *getSymbolTableEntryPtr(const MachOObjectFile *O, - DataRefImpl DRI) { - macho::SymtabLoadCommand S = O->getSymtabLoadCommand(); - - unsigned Index = DRI.d.b; - - unsigned SymbolTableEntrySize = O->is64Bit() ? - sizeof(macho::Symbol64TableEntry) : - sizeof(macho::SymbolTableEntry); - - uint64_t Offset = S.SymbolTableOffset + Index * SymbolTableEntrySize; - return getPtr(O, Offset); -} - static SymbolTableEntryBase getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { - const char *P = getSymbolTableEntryPtr(O, DRI); + const char *P = reinterpret_cast(DRI.p); return getStruct(O, P); } @@ -420,7 +406,10 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const { - Symb.d.b++; + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(macho::Symbol64TableEntry) : + sizeof(macho::SymbolTableEntry); + Symb.p += SymbolTableEntrySize; Res = SymbolRef(Symb, this); return object_error::success; } @@ -494,15 +483,15 @@ error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, } // Unfortunately symbols are unsorted so we need to touch all // symbols from load command - macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); - DRI.d.b = 0; - while (DRI.d.b <= Symtab.NumSymbolTableEntries) { + error_code ec; + for (symbol_iterator I = begin_symbols(), E = end_symbols(); I != E; + I.increment(ec)) { + DataRefImpl DRI = I->getRawDataRefImpl(); Entry = getSymbolTableEntryBase(this, DRI); getSymbolAddress(DRI, Value); if (Entry.SectionIndex == SectionIndex && Value > BeginOffset) if (!EndOffset || Value < EndOffset) EndOffset = Value; - DRI.d.b++; } if (!EndOffset) { uint64_t Size; @@ -829,11 +818,18 @@ MachOObjectFile::getRelocationSymbol(DataRefImpl Rel, SymbolRef &Res) const { macho::RelocationEntry RE = getRelocation(Rel); uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); bool isExtern = getPlainRelocationExternal(RE); + if (!isExtern) { + Res = *end_symbols(); + return object_error::success; + } + macho::SymtabLoadCommand S = getSymtabLoadCommand(); + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(macho::Symbol64TableEntry) : + sizeof(macho::SymbolTableEntry); + uint64_t Offset = S.SymbolTableOffset + SymbolIdx * SymbolTableEntrySize; DataRefImpl Sym; - if (isExtern) { - Sym.d.b = SymbolIdx; - } + Sym.p = reinterpret_cast(getPtr(this, Offset)); Res = SymbolRef(Sym, this); return object_error::success; } @@ -1160,17 +1156,27 @@ error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, } symbol_iterator MachOObjectFile::begin_symbols() const { - // DRI.d.a = segment number; DRI.d.b = symbol index. DataRefImpl DRI; + if (!SymtabLoadCmd) + return symbol_iterator(SymbolRef(DRI, this)); + + macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); + DRI.p = reinterpret_cast(getPtr(this, Symtab.SymbolTableOffset)); return symbol_iterator(SymbolRef(DRI, this)); } symbol_iterator MachOObjectFile::end_symbols() const { DataRefImpl DRI; - if (SymtabLoadCmd) { - macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); - DRI.d.b = Symtab.NumSymbolTableEntries; - } + if (!SymtabLoadCmd) + return symbol_iterator(SymbolRef(DRI, this)); + + macho::SymtabLoadCommand Symtab = getSymtabLoadCommand(); + unsigned SymbolTableEntrySize = is64Bit() ? + sizeof(macho::Symbol64TableEntry) : + sizeof(macho::SymbolTableEntry); + unsigned Offset = Symtab.SymbolTableOffset + + Symtab.NumSymbolTableEntries * SymbolTableEntrySize; + DRI.p = reinterpret_cast(getPtr(this, Offset)); return symbol_iterator(SymbolRef(DRI, this)); } @@ -1369,13 +1375,13 @@ macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { macho::SymbolTableEntry MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { - const char *P = getSymbolTableEntryPtr(this, DRI); + const char *P = reinterpret_cast(DRI.p); return getStruct(this, P); } macho::Symbol64TableEntry MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { - const char *P = getSymbolTableEntryPtr(this, DRI); + const char *P = reinterpret_cast(DRI.p); return getStruct(this, P); } diff --git a/test/tools/llvm-readobj/relocations.test b/test/tools/llvm-readobj/relocations.test index c23a7fe5bb..dec7f86298 100644 --- a/test/tools/llvm-readobj/relocations.test +++ b/test/tools/llvm-readobj/relocations.test @@ -34,8 +34,8 @@ MACHO-I386: Relocations [ MACHO-I386-NEXT: Section __text { MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts -MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main -MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 - +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 - MACHO-I386-NEXT: } MACHO-I386-NEXT: ] @@ -49,17 +49,17 @@ MACHO-X86-64-NEXT:] MACHO-PPC: Relocations [ MACHO-PPC-NEXT: Section __text { -MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 - MACHO-PPC-NEXT: } MACHO-PPC-NEXT: Section __picsymbolstub1 { -MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 - MACHO-PPC-NEXT: } MACHO-PPC-NEXT: Section __la_symbol_ptr { MACHO-PPC-NEXT: 0x0 0 2 1 PPC_RELOC_VANILLA 0 dyld_stub_binding_helper @@ -68,17 +68,17 @@ MACHO-PPC-NEXT: ] MACHO-PPC64: Relocations [ MACHO-PPC64-NEXT: Section __text { -MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x18 1 2 0 0 - MACHO-PPC64-NEXT: } MACHO-PPC64-NEXT: Section __picsymbolstub1 { -MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 - MACHO-PPC64-NEXT: } MACHO-PPC64-NEXT: Section __la_symbol_ptr { MACHO-PPC64-NEXT: 0x0 0 3 1 0 dyld_stub_binding_helper @@ -94,7 +94,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -103,7 +103,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -130,7 +130,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 1 MACHO-ARM-NEXT: Extern: 0 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 0 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -148,7 +148,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 0 MACHO-ARM-NEXT: Extern: 0 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 0 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -157,7 +157,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -166,7 +166,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: } diff --git a/test/tools/llvm-readobj/sections-ext.test b/test/tools/llvm-readobj/sections-ext.test index 526ddfe82c..327f040854 100644 --- a/test/tools/llvm-readobj/sections-ext.test +++ b/test/tools/llvm-readobj/sections-ext.test @@ -161,8 +161,8 @@ MACHO-I386-NEXT: Reserved2: 0x0 MACHO-I386-NEXT: Relocations [ MACHO-I386-NEXT: 0x18 1 2 1 GENERIC_RELOC_VANILLA 0 _SomeOtherFunction MACHO-I386-NEXT: 0x13 1 2 1 GENERIC_RELOC_VANILLA 0 _puts -MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 _main -MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 _main +MACHO-I386-NEXT: 0xB 0 2 n/a GENERIC_RELOC_LOCAL_SECTDIFF 1 - +MACHO-I386-NEXT: 0x0 0 2 n/a GENERIC_RELOC_PAIR 1 - MACHO-I386-NEXT: ] MACHO-I386-NEXT: Symbols [ MACHO-I386-NEXT: Symbol { @@ -275,11 +275,11 @@ MACHO-PPC-NEXT: ] MACHO-PPC-NEXT: Reserved1: 0x0 MACHO-PPC-NEXT: Reserved2: 0x0 MACHO-PPC-NEXT: Relocations [ -MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 _b +MACHO-PPC-NEXT: 0x24 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0x1C 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x58 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0x18 1 2 0 PPC_RELOC_BR24 0 - MACHO-PPC-NEXT: ] MACHO-PPC-NEXT: Symbols [ MACHO-PPC-NEXT: Symbol { @@ -317,10 +317,10 @@ MACHO-PPC-NEXT: ] MACHO-PPC-NEXT: Reserved1: 0x0 MACHO-PPC-NEXT: Reserved2: 0x20 MACHO-PPC-NEXT: Relocations [ -MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 _b -MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 _b -MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 _b +MACHO-PPC-NEXT: 0x14 0 2 n/a PPC_RELOC_LO16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x0 0 2 n/a PPC_RELOC_PAIR 1 - +MACHO-PPC-NEXT: 0xC 0 2 n/a PPC_RELOC_HA16_SECTDIFF 1 - +MACHO-PPC-NEXT: 0x20 0 2 n/a PPC_RELOC_PAIR 1 - MACHO-PPC-NEXT: ] MACHO-PPC-NEXT: Symbols [ MACHO-PPC-NEXT: ] @@ -430,11 +430,11 @@ MACHO-PPC64-NEXT: ] MACHO-PPC64-NEXT: Reserved1: 0x0 MACHO-PPC64-NEXT: Reserved2: 0x0 MACHO-PPC64-NEXT: Relocations [ -MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x18 1 2 0 0 _b +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x1C 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x58 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x18 1 2 0 0 - MACHO-PPC64-NEXT: ] MACHO-PPC64-NEXT: Symbols [ MACHO-PPC64-NEXT: Symbol { @@ -472,10 +472,10 @@ MACHO-PPC64-NEXT: ] MACHO-PPC64-NEXT: Reserved1: 0x0 MACHO-PPC64-NEXT: Reserved2: 0x20 MACHO-PPC64-NEXT: Relocations [ -MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 _b -MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 _b +MACHO-PPC64-NEXT: 0x14 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x0 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0xC 0 2 n/a 1 - +MACHO-PPC64-NEXT: 0x24 0 2 n/a 1 - MACHO-PPC64-NEXT: ] MACHO-PPC64-NEXT: Symbols [ MACHO-PPC64-NEXT: ] @@ -590,7 +590,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -599,7 +599,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -626,7 +626,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 1 MACHO-ARM-NEXT: Extern: 0 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 0 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -644,7 +644,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 0 MACHO-ARM-NEXT: Extern: 0 MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 0 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -653,7 +653,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_SECTDIFF (2) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: Relocation { @@ -662,7 +662,7 @@ MACHO-ARM-NEXT: PCRel: 0 MACHO-ARM-NEXT: Length: 2 MACHO-ARM-NEXT: Extern: N/A MACHO-ARM-NEXT: Type: ARM_RELOC_PAIR (1) -MACHO-ARM-NEXT: Symbol: _b +MACHO-ARM-NEXT: Symbol: - MACHO-ARM-NEXT: Scattered: 1 MACHO-ARM-NEXT: } MACHO-ARM-NEXT: ] diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index 10e53d91fb..31dc5ce24a 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -345,7 +345,9 @@ void MachODumper::printRelocation(const MachOObjectFile *Obj, if (error(RelI->getOffset(Offset))) return; if (error(RelI->getTypeName(RelocName))) return; if (error(RelI->getSymbol(Symbol))) return; - if (error(Symbol.getName(SymbolName))) return; + if (symbol_iterator(Symbol) != Obj->end_symbols() && + error(Symbol.getName(SymbolName))) + return; DataRefImpl DR = RelI->getRawDataRefImpl(); macho::RelocationEntry RE = Obj->getRelocation(DR); -- cgit v1.2.3-70-g09d2 From 956ca7265c697107708468b7e1b2fd21f4185bae Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 25 Apr 2013 12:28:45 +0000 Subject: Clarify getRelocationAddress x getRelocationOffset a bit. getRelocationAddress is for dynamic libraries and executables, getRelocationOffset for relocatable objects. Mark the getRelocationAddress of COFF and MachO as not implemented yet. Add a test of ELF's. llvm-readobj -r now prints the same values as readelf -r. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180259 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 49 ++++++++++++------------------ include/llvm/Object/RelocVisitor.h | 4 +-- lib/DebugInfo/DWARFContext.cpp | 2 +- lib/Object/COFFObjectFile.cpp | 3 +- lib/Object/MachOObjectFile.cpp | 16 +--------- test/Object/Inputs/hello-world.elf-x86-64 | Bin 0 -> 4544 bytes test/Object/relocation-executable.test | 18 +++++++++++ tools/llvm-objdump/MachODump.cpp | 2 +- tools/llvm-objdump/llvm-objdump.cpp | 8 ++--- tools/llvm-readobj/ELFDumper.cpp | 6 +++- tools/llvm-readobj/llvm-readobj.cpp | 4 +-- 11 files changed, 54 insertions(+), 58 deletions(-) create mode 100755 test/Object/Inputs/hello-world.elf-x86-64 create mode 100644 test/Object/relocation-executable.test (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 02840230f5..4f0e5b8db8 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -607,6 +607,8 @@ private: mutable const char *dt_soname; private: + uint64_t getROffset(DataRefImpl Rel) const; + // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. class VersionMapEntry : public PointerIntPair { @@ -1521,45 +1523,32 @@ error_code ELFObjectFile::getRelocationSymbol(DataRefImpl Rel, template error_code ELFObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; - const Elf_Shdr *sec = getSection(Rel.w.b); - switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } - } - - Result = offset; + assert((Header->e_type == ELF::ET_EXEC || Header->e_type == ELF::ET_DYN) && + "Only executable and shared objects files have addresses"); + Result = getROffset(Rel); return object_error::success; } template error_code ELFObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Result) const { - uint64_t offset; + assert(Header->e_type == ELF::ET_REL && + "Only relocatable object files have relocation offsets"); + Result = getROffset(Rel); + return object_error::success; +} + +template +uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { const Elf_Shdr *sec = getSection(Rel.w.b); switch (sec->sh_type) { - default : - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL : { - offset = getRel(Rel)->r_offset; - break; - } - case ELF::SHT_RELA : { - offset = getRela(Rel)->r_offset; - break; - } + default: + report_fatal_error("Invalid section type in Rel!"); + case ELF::SHT_REL: + return getRel(Rel)->r_offset; + case ELF::SHT_RELA: + return getRela(Rel)->r_offset; } - - Result = offset - sec->sh_addr; - return object_error::success; } template diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 2dcbdf9053..59d810763f 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -133,7 +133,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } @@ -151,7 +151,7 @@ private: int64_t Addend; R.getAdditionalInfo(Addend); uint64_t Address; - R.getAddress(Address); + R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp index 1e13731361..e5daf55982 100644 --- a/lib/DebugInfo/DWARFContext.cpp +++ b/lib/DebugInfo/DWARFContext.cpp @@ -572,7 +572,7 @@ DWARFContextInMemory::DWARFContextInMemory(object::ObjectFile *Obj) : reloc_e = i->end_relocations(); reloc_i != reloc_e; reloc_i.increment(ec)) { uint64_t Address; - reloc_i->getAddress(Address); + reloc_i->getOffset(Address); uint64_t Type; reloc_i->getType(Type); uint64_t SymAddr = 0; diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 46acd4d537..70fec321ba 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -705,8 +705,7 @@ error_code COFFObjectFile::getRelocationNext(DataRefImpl Rel, } error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { - Res = toRel(Rel)->VirtualAddress; - return object_error::success; + report_fatal_error("getRelocationAddress not implemented in COFFObjectFile"); } error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 51cd5b9a95..14bca2bf90 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -789,21 +789,7 @@ MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, uint64_t &Res) const { - uint64_t SectAddress; - DataRefImpl Sec; - Sec.d.a = Rel.d.b; - if (is64Bit()) { - macho::Section64 Sect = getSection64(Sec); - SectAddress = Sect.Address; - } else { - macho::Section Sect = getSection(Sec); - SectAddress = Sect.Address; - } - - macho::RelocationEntry RE = getRelocation(Rel); - uint64_t RelAddr = getAnyRelocationAddress(RE); - Res = SectAddress + RelAddr; - return object_error::success; + report_fatal_error("getRelocationAddress not implemented in MachOObjectFile"); } error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, diff --git a/test/Object/Inputs/hello-world.elf-x86-64 b/test/Object/Inputs/hello-world.elf-x86-64 new file mode 100755 index 0000000000..16092b8947 Binary files /dev/null and b/test/Object/Inputs/hello-world.elf-x86-64 differ diff --git a/test/Object/relocation-executable.test b/test/Object/relocation-executable.test new file mode 100644 index 0000000000..98f5b4ee2f --- /dev/null +++ b/test/Object/relocation-executable.test @@ -0,0 +1,18 @@ +RUN: llvm-readobj -r -expand-relocs %p/Inputs/hello-world.elf-x86-64 \ +RUN: | FileCheck %s + +// CHECK: Relocations [ +// CHECK: Section (11) .plt { +// CHECK-NEXT: Relocation { +// CHECK-NEXT: Offset: 0x4018F8 +// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT (7) +// CHECK-NEXT: Symbol: __libc_start_main +// CHECK-NEXT: Info: 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: Relocation { +// CHECK-NEXT: Offset: 0x401900 +// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT (7) +// CHECK-NEXT: Symbol: puts +// CHECK-NEXT: Info: 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: } diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index d78d7f31a6..6797e2dc5b 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -343,7 +343,7 @@ static void DisassembleInputMachO2(StringRef Filename, for (relocation_iterator RI = Sections[SectIdx].begin_relocations(), RE = Sections[SectIdx].end_relocations(); RI != RE; RI.increment(ec)) { uint64_t RelocOffset, SectionAddress; - RI->getAddress(RelocOffset); + RI->getOffset(RelocOffset); Sections[SectIdx].getAddress(SectionAddress); RelocOffset -= SectionAddress; diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index 9985599565..247b90f030 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -186,8 +186,8 @@ void llvm::DumpBytes(StringRef bytes) { bool llvm::RelocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getAddress(a_addr))) return false; - if (error(b.getAddress(b_addr))) return false; + if (error(a.getOffset(a_addr))) return false; + if (error(b.getOffset(b_addr))) return false; return a_addr < b_addr; } @@ -378,7 +378,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { if (error(rel_cur->getHidden(hidden))) goto skip_print_rel; if (hidden) goto skip_print_rel; - if (error(rel_cur->getAddress(addr))) goto skip_print_rel; + if (error(rel_cur->getOffset(addr))) goto skip_print_rel; // Stop when rel_cur's address is past the current instruction. if (addr >= Index + Size) break; if (error(rel_cur->getTypeName(name))) goto skip_print_rel; @@ -417,7 +417,7 @@ static void PrintRelocations(const ObjectFile *o) { if (error(ri->getHidden(hidden))) continue; if (hidden) continue; if (error(ri->getTypeName(relocname))) continue; - if (error(ri->getAddress(address))) continue; + if (error(ri->getOffset(address))) continue; if (error(ri->getValueString(valuestr))) continue; outs() << address << " " << relocname << " " << valuestr << "\n"; } diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index f771cbdd52..ea1b83f32f 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -582,7 +582,11 @@ void ELFDumper::printRelocation(section_iterator Sec, int64_t Info; StringRef SymbolName; SymbolRef Symbol; - if (error(RelI->getOffset(Offset))) return; + if (Obj->getElfHeader()->e_type == ELF::ET_REL){ + if (error(RelI->getOffset(Offset))) return; + } else { + if (error(RelI->getAddress(Offset))) return; + } if (error(RelI->getType(RelocType))) return; if (error(RelI->getTypeName(RelocName))) return; if (error(RelI->getAdditionalInfo(Info))) return; diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 7a4b4e4431..2e95b6b551 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -143,8 +143,8 @@ bool error(error_code EC) { bool relocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getAddress(a_addr))) return false; - if (error(b.getAddress(b_addr))) return false; + if (error(a.getOffset(a_addr))) return false; + if (error(b.getOffset(b_addr))) return false; return a_addr < b_addr; } -- cgit v1.2.3-70-g09d2 From e5330f77cf420d71cfd46c960387eb06edeccbf8 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 25 Apr 2013 12:45:46 +0000 Subject: Use a pointer as the relocation iterator. Since the relocation iterator walks only the relocations in one section, we can just use a pointer and avoid fetching information about the section at every reference. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180262 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Object/MachOObjectFile.cpp | 53 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 14bca2bf90..38198b1793 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -758,31 +758,47 @@ MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, } relocation_iterator MachOObjectFile::getSectionRelBegin(DataRefImpl Sec) const { - DataRefImpl ret; - ret.d.b = Sec.d.a; - return relocation_iterator(RelocationRef(ret, this)); + uint32_t Offset; + if (is64Bit()) { + macho::Section64 Sect = getSection64(Sec); + Offset = Sect.RelocationTableOffset; + } else { + macho::Section Sect = getSection(Sec); + Offset = Sect.RelocationTableOffset; + } + + DataRefImpl Ret; + Ret.p = reinterpret_cast(getPtr(this, Offset)); + return relocation_iterator(RelocationRef(Ret, this)); } relocation_iterator MachOObjectFile::getSectionRelEnd(DataRefImpl Sec) const { - uint32_t LastReloc; + uint32_t Offset; + uint32_t Num; if (is64Bit()) { macho::Section64 Sect = getSection64(Sec); - LastReloc = Sect.NumRelocationTableEntries; + Offset = Sect.RelocationTableOffset; + Num = Sect.NumRelocationTableEntries; } else { macho::Section Sect = getSection(Sec); - LastReloc = Sect.NumRelocationTableEntries; + Offset = Sect.RelocationTableOffset; + Num = Sect.NumRelocationTableEntries; } + const macho::RelocationEntry *P = + reinterpret_cast(getPtr(this, Offset)); + DataRefImpl Ret; - Ret.d.a = LastReloc; - Ret.d.b = Sec.d.a; + Ret.p = reinterpret_cast(P + Num); return relocation_iterator(RelocationRef(Ret, this)); } - error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, - RelocationRef &Res) const { - ++Rel.d.a; +error_code MachOObjectFile::getRelocationNext(DataRefImpl Rel, + RelocationRef &Res) const { + const macho::RelocationEntry *P = + reinterpret_cast(Rel.p); + Rel.p = reinterpret_cast(P + 1); Res = RelocationRef(Rel, this); return object_error::success; } @@ -1378,19 +1394,8 @@ MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandIn macho::RelocationEntry MachOObjectFile::getRelocation(DataRefImpl Rel) const { - uint32_t RelOffset; - DataRefImpl Sec; - Sec.d.a = Rel.d.b; - if (is64Bit()) { - macho::Section64 Sect = getSection64(Sec); - RelOffset = Sect.RelocationTableOffset; - } else { - macho::Section Sect = getSection(Sec); - RelOffset = Sect.RelocationTableOffset; - } - - uint64_t Offset = RelOffset + Rel.d.a * sizeof(macho::RelocationEntry); - return getStruct(this, getPtr(this, Offset)); + const char *P = reinterpret_cast(Rel.p); + return getStruct(this, P); } macho::Header MachOObjectFile::getHeader() const { -- cgit v1.2.3-70-g09d2 From 2173e1839c2d00f7f980450dd537047b7b376e6b Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 26 Apr 2013 20:07:33 +0000 Subject: Use llvm/Object/MachO.h in macho-dumper. Drop the old macho parser. For Mach-O there were 2 implementations for parsing object files. A standalone llvm/Object/MachOObject.h and llvm/Object/MachO.h which implements the generic interface in llvm/Object/ObjectFile.h. This patch adds the missing features to MachO.h, moves macho-dump to use MachO.h and removes ObjectFile.h. In addition to making sure that check-all is clean, I checked that the new version produces exactly the same output in all Mach-O files in a llvm+clang build directory (including executables and shared libraries). To test the performance, I ran macho-dump over all the files in a llvm+clang build directory again, but this time redirecting the output to /dev/null. Both the old and new versions take about 4.6 seconds (2.5 user) to finish. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180624 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ADT/InMemoryStruct.h | 77 ---- include/llvm/Object/MachO.h | 22 ++ include/llvm/Object/MachOObject.h | 212 ----------- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 2 +- lib/Object/CMakeLists.txt | 1 - lib/Object/MachOObject.cpp | 422 -------------------- lib/Object/MachOObjectFile.cpp | 161 ++++++-- tools/llvm-rtdyld/llvm-rtdyld.cpp | 2 +- tools/macho-dump/macho-dump.cpp | 424 ++++++++++----------- 9 files changed, 347 insertions(+), 976 deletions(-) delete mode 100644 include/llvm/ADT/InMemoryStruct.h delete mode 100644 include/llvm/Object/MachOObject.h delete mode 100644 lib/Object/MachOObject.cpp (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/ADT/InMemoryStruct.h b/include/llvm/ADT/InMemoryStruct.h deleted file mode 100644 index a56084501a..0000000000 --- a/include/llvm/ADT/InMemoryStruct.h +++ /dev/null @@ -1,77 +0,0 @@ -//===- InMemoryStruct.h - Indirect Struct Access Smart Pointer --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_INMEMORYSTRUCT_H -#define LLVM_ADT_INMEMORYSTRUCT_H - -#include - -namespace llvm { - -/// \brief Helper object for abstracting access to an in-memory structure which -/// may require some kind of temporary storage. -/// -/// This class is designed to be used for accessing file data structures which -/// in the common case can be accessed from a direct pointer to a memory mapped -/// object, but which in some cases may require indirect access to a temporary -/// structure (which, for example, may have undergone endianness translation). -template -class InMemoryStruct { - typedef T value_type; - typedef value_type &reference; - typedef value_type *pointer; - typedef const value_type &const_reference; - typedef const value_type *const_pointer; - - /// \brief The smart pointer target. - value_type *Target; - - /// \brief A temporary object which can be used as a target of the smart - /// pointer. - value_type Contents; - -private: - -public: - InMemoryStruct() : Target(0) {} - InMemoryStruct(reference Value) : Target(&Contents), Contents(Value) {} - InMemoryStruct(pointer Value) : Target(Value) {} - InMemoryStruct(const InMemoryStruct &Value) { *this = Value; } - - void operator=(const InMemoryStruct &Value) { - if (Value.Target != &Value.Contents) { - Target = Value.Target; - } else { - Target = &Contents; - Contents = Value.Contents; - } - } - - const_reference operator*() const { - assert(Target && "Cannot dereference null pointer"); - return *Target; - } - reference operator*() { - assert(Target && "Cannot dereference null pointer"); - return *Target; - } - - const_pointer operator->() const { - return Target; - } - pointer operator->() { - return Target; - } - - operator bool() const { return Target != 0; } -}; - -} - -#endif diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index d8598ebdcf..98d3788e44 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -106,6 +106,9 @@ public: virtual StringRef getLoadName() const; + relocation_iterator getSectionRelBegin(unsigned Index) const; + relocation_iterator getSectionRelEnd(unsigned Index) const; + // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment // a section should be put in in the final object. @@ -134,14 +137,32 @@ public: // MachO specific structures. macho::Section getSection(DataRefImpl DRI) const; macho::Section64 getSection64(DataRefImpl DRI) const; + macho::Section getSection(const LoadCommandInfo &L, unsigned Index) const; + macho::Section64 getSection64(const LoadCommandInfo &L, unsigned Index) const; macho::SymbolTableEntry getSymbolTableEntry(DataRefImpl DRI) const; macho::Symbol64TableEntry getSymbol64TableEntry(DataRefImpl DRI) const; + macho::LinkeditDataLoadCommand getLinkeditDataLoadCommand(const LoadCommandInfo &L) const; + macho::SegmentLoadCommand + getSegmentLoadCommand(const LoadCommandInfo &L) const; + macho::Segment64LoadCommand + getSegment64LoadCommand(const LoadCommandInfo &L) const; + macho::LinkerOptionsLoadCommand + getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + macho::RelocationEntry getRelocation(DataRefImpl Rel) const; macho::Header getHeader() const; + macho::Header64Ext getHeader64Ext() const; + macho::IndirectSymbolTableEntry + getIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, + unsigned Index) const; + macho::DataInCodeTableEntry getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const; macho::SymtabLoadCommand getSymtabLoadCommand() const; + macho::DysymtabLoadCommand getDysymtabLoadCommand() const; + StringRef getStringTableData() const; bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; @@ -153,6 +174,7 @@ private: typedef SmallVector SectionList; SectionList Sections; const char *SymtabLoadCmd; + const char *DysymtabLoadCmd; }; } diff --git a/include/llvm/Object/MachOObject.h b/include/llvm/Object/MachOObject.h deleted file mode 100644 index 50ee25b463..0000000000 --- a/include/llvm/Object/MachOObject.h +++ /dev/null @@ -1,212 +0,0 @@ -//===- MachOObject.h - Mach-O Object File Wrapper ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_OBJECT_MACHOOBJECT_H -#define LLVM_OBJECT_MACHOOBJECT_H - -#include "llvm/ADT/InMemoryStruct.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Object/MachOFormat.h" -#include - -namespace llvm { - -class MemoryBuffer; -class raw_ostream; - -namespace object { - -/// \brief Wrapper object for manipulating Mach-O object files. -/// -/// This class is designed to implement a full-featured, efficient, portable, -/// and robust Mach-O interface to Mach-O object files. It does not attempt to -/// smooth over rough edges in the Mach-O format or generalize access to object -/// independent features. -/// -/// The class is designed around accessing the Mach-O object which is expected -/// to be fully loaded into memory. -/// -/// This class is *not* suitable for concurrent use. For efficient operation, -/// the class uses APIs which rely on the ability to cache the results of -/// certain calls in internal objects which are not safe for concurrent -/// access. This allows the API to be zero-copy on the common paths. -// -// FIXME: It would be cool if we supported a "paged" MemoryBuffer -// implementation. This would allow us to implement a more sensible version of -// MemoryObject which can work like a MemoryBuffer, but be more efficient for -// objects which are in the current address space. -class MachOObject { -public: - struct LoadCommandInfo { - /// The load command information. - macho::LoadCommand Command; - - /// The offset to the start of the load command in memory. - uint64_t Offset; - }; - -private: - OwningPtr Buffer; - - /// Whether the object is little endian. - bool IsLittleEndian; - /// Whether the object is 64-bit. - bool Is64Bit; - /// Whether the object is swapped endianness from the host. - bool IsSwappedEndian; - /// Whether the string table has been registered. - bool HasStringTable; - - /// The cached information on the load commands. - LoadCommandInfo *LoadCommands; - mutable unsigned NumLoadedCommands; - - /// The cached copy of the header. - macho::Header Header; - macho::Header64Ext Header64Ext; - - /// Cache string table information. - StringRef StringTable; - -private: - MachOObject(MemoryBuffer *Buffer, bool IsLittleEndian, bool Is64Bit); - -public: - ~MachOObject(); - - /// \brief Load a Mach-O object from a MemoryBuffer object. - /// - /// \param Buffer - The buffer to load the object from. This routine takes - /// exclusive ownership of the buffer (which is passed to the returned object - /// on success). - /// \param ErrorStr [out] - If given, will be set to a user readable error - /// message on failure. - /// \returns The loaded object, or null on error. - static MachOObject *LoadFromBuffer(MemoryBuffer *Buffer, - std::string *ErrorStr = 0); - - /// @name File Information - /// @{ - - bool isLittleEndian() const { return IsLittleEndian; } - bool isSwappedEndian() const { return IsSwappedEndian; } - bool is64Bit() const { return Is64Bit; } - - unsigned getHeaderSize() const { - return Is64Bit ? macho::Header64Size : macho::Header32Size; - } - - StringRef getData(size_t Offset, size_t Size) const; - - /// @} - /// @name String Table Data - /// @{ - - StringRef getStringTableData() const { - assert(HasStringTable && "String table has not been registered!"); - return StringTable; - } - - StringRef getStringAtIndex(unsigned Index) const { - size_t End = getStringTableData().find('\0', Index); - return getStringTableData().slice(Index, End); - } - - void RegisterStringTable(macho::SymtabLoadCommand &SLC); - - /// @} - /// @name Object Header Access - /// @{ - - const macho::Header &getHeader() const { return Header; } - const macho::Header64Ext &getHeader64Ext() const { - assert(is64Bit() && "Invalid access!"); - return Header64Ext; - } - - /// @} - /// @name Object Structure Access - /// @{ - - // TODO: Would be useful to have an iterator based version - // of this. - /// \brief Retrieve the information for the given load command. - const LoadCommandInfo &getLoadCommandInfo(unsigned Index) const; - - void ReadSegmentLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadSegment64LoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadSymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadDysymtabLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadLinkeditDataLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadLinkerOptionsLoadCommand( - const LoadCommandInfo &LCI, - InMemoryStruct &Res) const; - void ReadIndirectSymbolTableEntry( - const macho::DysymtabLoadCommand &DLC, - unsigned Index, - InMemoryStruct &Res) const; - void ReadSection( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct &Res) const; - void ReadSection64( - const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct &Res) const; - void ReadRelocationEntry( - uint64_t RelocationTableOffset, unsigned Index, - InMemoryStruct &Res) const; - void ReadSymbolTableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct &Res) const; - void ReadSymbol64TableEntry( - uint64_t SymbolTableOffset, unsigned Index, - InMemoryStruct &Res) const; - void ReadDataInCodeTableEntry( - uint64_t TableOffset, unsigned Index, - InMemoryStruct &Res) const; - void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const; - - /// @} - - /// @name Object Dump Facilities - /// @{ - /// dump - Support for debugging, callable in GDB: V->dump() - // - void dump() const; - void dumpHeader() const; - - /// print - Implement operator<< on Value. - /// - void print(raw_ostream &O) const; - void printHeader(raw_ostream &O) const; - - /// @} -}; - -inline raw_ostream &operator<<(raw_ostream &OS, const MachOObject &V) { - V.print(OS); - return OS; -} - -} // end namespace object -} // end namespace llvm - -#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 62d8487078..f581b3f824 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -16,7 +16,7 @@ #include "RuntimeDyldImpl.h" #include "llvm/ADT/IndexedMap.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/Format.h" using namespace llvm; diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index c20fc0cc39..4ed129f467 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -4,7 +4,6 @@ add_llvm_library(LLVMObject COFFObjectFile.cpp ELFObjectFile.cpp Error.cpp - MachOObject.cpp MachOObjectFile.cpp Object.cpp ObjectFile.cpp diff --git a/lib/Object/MachOObject.cpp b/lib/Object/MachOObject.cpp deleted file mode 100644 index d88f96f298..0000000000 --- a/lib/Object/MachOObject.cpp +++ /dev/null @@ -1,422 +0,0 @@ -//===- MachOObject.cpp - Mach-O Object File Wrapper -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Object/MachOObject.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/SwapByteOrder.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; -using namespace llvm::object; - -/* Translation Utilities */ - -template -static void SwapValue(T &Value) { - Value = sys::SwapByteOrder(Value); -} - -template -static void SwapStruct(T &Value); - -template -static void ReadInMemoryStruct(const MachOObject &MOO, - StringRef Buffer, uint64_t Base, - InMemoryStruct &Res) { - typedef T struct_type; - uint64_t Size = sizeof(struct_type); - - // Check that the buffer contains the expected data. - if (Base + Size > Buffer.size()) { - Res = 0; - return; - } - - // Check whether we can return a direct pointer. - struct_type *Ptr = reinterpret_cast( - const_cast(Buffer.data() + Base)); - if (!MOO.isSwappedEndian()) { - Res = Ptr; - return; - } - - // Otherwise, copy the struct and translate the values. - Res = *Ptr; - SwapStruct(*Res); -} - -/* *** */ - -MachOObject::MachOObject(MemoryBuffer *Buffer_, bool IsLittleEndian_, - bool Is64Bit_) - : Buffer(Buffer_), IsLittleEndian(IsLittleEndian_), Is64Bit(Is64Bit_), - IsSwappedEndian(IsLittleEndian != sys::IsLittleEndianHost), - HasStringTable(false), LoadCommands(0), NumLoadedCommands(0) { - // Load the common header. - memcpy(&Header, Buffer->getBuffer().data(), sizeof(Header)); - if (IsSwappedEndian) { - SwapValue(Header.Magic); - SwapValue(Header.CPUType); - SwapValue(Header.CPUSubtype); - SwapValue(Header.FileType); - SwapValue(Header.NumLoadCommands); - SwapValue(Header.SizeOfLoadCommands); - SwapValue(Header.Flags); - } - - if (is64Bit()) { - memcpy(&Header64Ext, Buffer->getBuffer().data() + sizeof(Header), - sizeof(Header64Ext)); - if (IsSwappedEndian) { - SwapValue(Header64Ext.Reserved); - } - } - - // Create the load command array if sane. - if (getHeader().NumLoadCommands < (1 << 20)) - LoadCommands = new LoadCommandInfo[getHeader().NumLoadCommands]; -} - -MachOObject::~MachOObject() { - delete [] LoadCommands; -} - -MachOObject *MachOObject::LoadFromBuffer(MemoryBuffer *Buffer, - std::string *ErrorStr) { - // First, check the magic value and initialize the basic object info. - bool IsLittleEndian = false, Is64Bit = false; - StringRef Magic = Buffer->getBuffer().slice(0, 4); - if (Magic == "\xFE\xED\xFA\xCE") { - } else if (Magic == "\xCE\xFA\xED\xFE") { - IsLittleEndian = true; - } else if (Magic == "\xFE\xED\xFA\xCF") { - Is64Bit = true; - } else if (Magic == "\xCF\xFA\xED\xFE") { - IsLittleEndian = true; - Is64Bit = true; - } else { - if (ErrorStr) *ErrorStr = "not a Mach object file (invalid magic)"; - return 0; - } - - // Ensure that the at least the full header is present. - unsigned HeaderSize = Is64Bit ? macho::Header64Size : macho::Header32Size; - if (Buffer->getBufferSize() < HeaderSize) { - if (ErrorStr) *ErrorStr = "not a Mach object file (invalid header)"; - return 0; - } - - OwningPtr Object(new MachOObject(Buffer, IsLittleEndian, - Is64Bit)); - - // Check for bogus number of load commands. - if (Object->getHeader().NumLoadCommands >= (1 << 20)) { - if (ErrorStr) *ErrorStr = "not a Mach object file (unreasonable header)"; - return 0; - } - - if (ErrorStr) *ErrorStr = ""; - return Object.take(); -} - -StringRef MachOObject::getData(size_t Offset, size_t Size) const { - return Buffer->getBuffer().substr(Offset,Size); -} - -void MachOObject::RegisterStringTable(macho::SymtabLoadCommand &SLC) { - HasStringTable = true; - StringTable = Buffer->getBuffer().substr(SLC.StringTableOffset, - SLC.StringTableSize); -} - -const MachOObject::LoadCommandInfo & -MachOObject::getLoadCommandInfo(unsigned Index) const { - assert(Index < getHeader().NumLoadCommands && "Invalid index!"); - - // Load the command, if necessary. - if (Index >= NumLoadedCommands) { - uint64_t Offset; - if (Index == 0) { - Offset = getHeaderSize(); - } else { - const LoadCommandInfo &Prev = getLoadCommandInfo(Index - 1); - Offset = Prev.Offset + Prev.Command.Size; - } - - LoadCommandInfo &Info = LoadCommands[Index]; - memcpy(&Info.Command, Buffer->getBuffer().data() + Offset, - sizeof(macho::LoadCommand)); - if (IsSwappedEndian) { - SwapValue(Info.Command.Type); - SwapValue(Info.Command.Size); - } - Info.Offset = Offset; - NumLoadedCommands = Index + 1; - } - - return LoadCommands[Index]; -} - -template<> -void SwapStruct(macho::SegmentLoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.VMAddress); - SwapValue(Value.VMSize); - SwapValue(Value.FileOffset); - SwapValue(Value.FileSize); - SwapValue(Value.MaxVMProtection); - SwapValue(Value.InitialVMProtection); - SwapValue(Value.NumSections); - SwapValue(Value.Flags); -} -void MachOObject::ReadSegmentLoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::Segment64LoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.VMAddress); - SwapValue(Value.VMSize); - SwapValue(Value.FileOffset); - SwapValue(Value.FileSize); - SwapValue(Value.MaxVMProtection); - SwapValue(Value.InitialVMProtection); - SwapValue(Value.NumSections); - SwapValue(Value.Flags); -} -void MachOObject::ReadSegment64LoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::SymtabLoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.SymbolTableOffset); - SwapValue(Value.NumSymbolTableEntries); - SwapValue(Value.StringTableOffset); - SwapValue(Value.StringTableSize); -} -void MachOObject::ReadSymtabLoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::DysymtabLoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.LocalSymbolsIndex); - SwapValue(Value.NumLocalSymbols); - SwapValue(Value.ExternalSymbolsIndex); - SwapValue(Value.NumExternalSymbols); - SwapValue(Value.UndefinedSymbolsIndex); - SwapValue(Value.NumUndefinedSymbols); - SwapValue(Value.TOCOffset); - SwapValue(Value.NumTOCEntries); - SwapValue(Value.ModuleTableOffset); - SwapValue(Value.NumModuleTableEntries); - SwapValue(Value.ReferenceSymbolTableOffset); - SwapValue(Value.NumReferencedSymbolTableEntries); - SwapValue(Value.IndirectSymbolTableOffset); - SwapValue(Value.NumIndirectSymbolTableEntries); - SwapValue(Value.ExternalRelocationTableOffset); - SwapValue(Value.NumExternalRelocationTableEntries); - SwapValue(Value.LocalRelocationTableOffset); - SwapValue(Value.NumLocalRelocationTableEntries); -} -void MachOObject::ReadDysymtabLoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::LinkeditDataLoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.DataOffset); - SwapValue(Value.DataSize); -} -void MachOObject::ReadLinkeditDataLoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::LinkerOptionsLoadCommand &Value) { - SwapValue(Value.Type); - SwapValue(Value.Size); - SwapValue(Value.Count); -} -void MachOObject::ReadLinkerOptionsLoadCommand(const LoadCommandInfo &LCI, - InMemoryStruct &Res) const { - ReadInMemoryStruct(*this, Buffer->getBuffer(), LCI.Offset, Res); -} - -template<> -void SwapStruct(macho::IndirectSymbolTableEntry &Value) { - SwapValue(Value.Index); -} -void -MachOObject::ReadIndirectSymbolTableEntry(const macho::DysymtabLoadCommand &DLC, - unsigned Index, - InMemoryStruct &Res) const { - uint64_t Offset = (DLC.IndirectSymbolTableOffset + - Index * sizeof(macho::IndirectSymbolTableEntry)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - - -template<> -void SwapStruct(macho::Section &Value) { - SwapValue(Value.Address); - SwapValue(Value.Size); - SwapValue(Value.Offset); - SwapValue(Value.Align); - SwapValue(Value.RelocationTableOffset); - SwapValue(Value.NumRelocationTableEntries); - SwapValue(Value.Flags); - SwapValue(Value.Reserved1); - SwapValue(Value.Reserved2); -} -void MachOObject::ReadSection(const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct &Res) const { - assert(LCI.Command.Type == macho::LCT_Segment && - "Unexpected load command info!"); - uint64_t Offset = (LCI.Offset + sizeof(macho::SegmentLoadCommand) + - Index * sizeof(macho::Section)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -template<> -void SwapStruct(macho::Section64 &Value) { - SwapValue(Value.Address); - SwapValue(Value.Size); - SwapValue(Value.Offset); - SwapValue(Value.Align); - SwapValue(Value.RelocationTableOffset); - SwapValue(Value.NumRelocationTableEntries); - SwapValue(Value.Flags); - SwapValue(Value.Reserved1); - SwapValue(Value.Reserved2); - SwapValue(Value.Reserved3); -} -void MachOObject::ReadSection64(const LoadCommandInfo &LCI, - unsigned Index, - InMemoryStruct &Res) const { - assert(LCI.Command.Type == macho::LCT_Segment64 && - "Unexpected load command info!"); - uint64_t Offset = (LCI.Offset + sizeof(macho::Segment64LoadCommand) + - Index * sizeof(macho::Section64)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -template<> -void SwapStruct(macho::RelocationEntry &Value) { - SwapValue(Value.Word0); - SwapValue(Value.Word1); -} -void MachOObject::ReadRelocationEntry(uint64_t RelocationTableOffset, - unsigned Index, - InMemoryStruct &Res) const { - uint64_t Offset = (RelocationTableOffset + - Index * sizeof(macho::RelocationEntry)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -template<> -void SwapStruct(macho::SymbolTableEntry &Value) { - SwapValue(Value.StringIndex); - SwapValue(Value.Flags); - SwapValue(Value.Value); -} -void MachOObject::ReadSymbolTableEntry(uint64_t SymbolTableOffset, - unsigned Index, - InMemoryStruct &Res) const { - uint64_t Offset = (SymbolTableOffset + - Index * sizeof(macho::SymbolTableEntry)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -template<> -void SwapStruct(macho::Symbol64TableEntry &Value) { - SwapValue(Value.StringIndex); - SwapValue(Value.Flags); - SwapValue(Value.Value); -} -void MachOObject::ReadSymbol64TableEntry(uint64_t SymbolTableOffset, - unsigned Index, - InMemoryStruct &Res) const { - uint64_t Offset = (SymbolTableOffset + - Index * sizeof(macho::Symbol64TableEntry)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -template<> -void SwapStruct(macho::DataInCodeTableEntry &Value) { - SwapValue(Value.Offset); - SwapValue(Value.Length); - SwapValue(Value.Kind); -} -void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset, - unsigned Index, - InMemoryStruct &Res) const { - uint64_t Offset = (TableOffset + - Index * sizeof(macho::DataInCodeTableEntry)); - ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res); -} - -void MachOObject::ReadULEB128s(uint64_t Index, - SmallVectorImpl &Out) const { - DataExtractor extractor(Buffer->getBuffer(), true, 0); - - uint32_t offset = Index; - uint64_t data = 0; - while (uint64_t delta = extractor.getULEB128(&offset)) { - data += delta; - Out.push_back(data); - } -} - -/* ** */ -// Object Dumping Facilities -void MachOObject::dump() const { print(dbgs()); dbgs() << '\n'; } -void MachOObject::dumpHeader() const { printHeader(dbgs()); dbgs() << '\n'; } - -void MachOObject::printHeader(raw_ostream &O) const { - O << "('cputype', " << Header.CPUType << ")\n"; - O << "('cpusubtype', " << Header.CPUSubtype << ")\n"; - O << "('filetype', " << Header.FileType << ")\n"; - O << "('num_load_commands', " << Header.NumLoadCommands << ")\n"; - O << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n"; - O << "('flag', " << Header.Flags << ")\n"; - - // Print extended header if 64-bit. - if (is64Bit()) - O << "('reserved', " << Header64Ext.Reserved << ")\n"; -} - -void MachOObject::print(raw_ostream &O) const { - O << "Header:\n"; - printHeader(O); - O << "Load Commands:\n"; - - O << "Buffer:\n"; -} diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 38198b1793..bb6ca93176 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -119,6 +119,11 @@ void SwapStruct(macho::Header &H) { SwapValue(H.Flags); } +template<> +void SwapStruct(macho::Header64Ext &E) { + SwapValue(E.Reserved); +} + template<> void SwapStruct(macho::SymtabLoadCommand &C) { SwapValue(C.Type); @@ -129,6 +134,30 @@ void SwapStruct(macho::SymtabLoadCommand &C) { SwapValue(C.StringTableSize); } +template<> +void SwapStruct(macho::DysymtabLoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.LocalSymbolsIndex); + SwapValue(C.NumLocalSymbols); + SwapValue(C.ExternalSymbolsIndex); + SwapValue(C.NumExternalSymbols); + SwapValue(C.UndefinedSymbolsIndex); + SwapValue(C.NumUndefinedSymbols); + SwapValue(C.TOCOffset); + SwapValue(C.NumTOCEntries); + SwapValue(C.ModuleTableOffset); + SwapValue(C.NumModuleTableEntries); + SwapValue(C.ReferenceSymbolTableOffset); + SwapValue(C.NumReferencedSymbolTableEntries); + SwapValue(C.IndirectSymbolTableOffset); + SwapValue(C.NumIndirectSymbolTableEntries); + SwapValue(C.ExternalRelocationTableOffset); + SwapValue(C.NumExternalRelocationTableEntries); + SwapValue(C.LocalRelocationTableOffset); + SwapValue(C.NumLocalRelocationTableEntries); +} + template<> void SwapStruct(macho::LinkeditDataLoadCommand &C) { SwapValue(C.Type); @@ -165,6 +194,25 @@ void SwapStruct(macho::Segment64LoadCommand &C) { SwapValue(C.Flags); } +template<> +void SwapStruct(macho::IndirectSymbolTableEntry &C) { + SwapValue(C.Index); +} + +template<> +void SwapStruct(macho::LinkerOptionsLoadCommand &C) { + SwapValue(C.Type); + SwapValue(C.Size); + SwapValue(C.Count); +} + +template<> +void SwapStruct(macho::DataInCodeTableEntry &C) { + SwapValue(C.Offset); + SwapValue(C.Length); + SwapValue(C.Kind); +} + template T getStruct(const MachOObjectFile *O, const char *P) { T Cmd; @@ -174,32 +222,20 @@ T getStruct(const MachOObjectFile *O, const char *P) { return Cmd; } -static macho::SegmentLoadCommand -getSegmentLoadCommand(const MachOObjectFile *O, - const MachOObjectFile::LoadCommandInfo &L) { - return getStruct(O, L.Ptr); -} - -static macho::Segment64LoadCommand -getSegment64LoadCommand(const MachOObjectFile *O, - const MachOObjectFile::LoadCommandInfo &L) { - return getStruct(O, L.Ptr); -} - static uint32_t getSegmentLoadCommandNumSections(const MachOObjectFile *O, const MachOObjectFile::LoadCommandInfo &L) { if (O->is64Bit()) { - macho::Segment64LoadCommand S = getSegment64LoadCommand(O, L); + macho::Segment64LoadCommand S = O->getSegment64LoadCommand(L); return S.NumSections; } - macho::SegmentLoadCommand S = getSegmentLoadCommand(O, L); + macho::SegmentLoadCommand S = O->getSegmentLoadCommand(L); return S.NumSections; } -static const SectionBase * -getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, - unsigned Sec) { +static const char * +getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, + unsigned Sec) { uintptr_t CommandAddr = reinterpret_cast(L.Ptr); bool Is64 = O->is64Bit(); @@ -209,7 +245,7 @@ getSectionBase(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, sizeof(macho::Section); uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; - return reinterpret_cast(SectionAddr); + return reinterpret_cast(SectionAddr); } static const char *getPtr(const MachOObjectFile *O, size_t Offset) { @@ -377,7 +413,7 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, bool IsLittleEndian, bool Is64bits, error_code &ec) : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), - SymtabLoadCmd(NULL) { + SymtabLoadCmd(NULL), DysymtabLoadCmd(NULL) { uint32_t LoadCommandCount = this->getHeader().NumLoadCommands; macho::LoadCommandType SegmentLoadType = is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment; @@ -387,13 +423,14 @@ MachOObjectFile::MachOObjectFile(MemoryBuffer *Object, if (Load.C.Type == macho::LCT_Symtab) { assert(!SymtabLoadCmd && "Multiple symbol tables"); SymtabLoadCmd = Load.Ptr; - } - - if (Load.C.Type == SegmentLoadType) { + } else if (Load.C.Type == macho::LCT_Dysymtab) { + assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); + DysymtabLoadCmd = Load.Ptr; + } else if (Load.C.Type == SegmentLoadType) { uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); for (unsigned J = 0; J < NumSections; ++J) { - const SectionBase *Sec = getSectionBase(this, Load, J); - Sections.push_back(reinterpret_cast(Sec)); + const char *Sec = getSectionPtr(this, Load, J); + Sections.push_back(Sec); } } @@ -416,10 +453,9 @@ error_code MachOObjectFile::getSymbolNext(DataRefImpl Symb, error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, StringRef &Res) const { - macho::SymtabLoadCommand S = getSymtabLoadCommand(); - const char *StringTable = getPtr(this, S.StringTableOffset); + StringRef StringTable = getStringTableData(); SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, Symb); - const char *Start = &StringTable[Entry.StringIndex]; + const char *Start = &StringTable.data()[Entry.StringIndex]; Res = StringRef(Start); return object_error::success; } @@ -1271,6 +1307,18 @@ StringRef MachOObjectFile::getLoadName() const { report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); } +relocation_iterator MachOObjectFile::getSectionRelBegin(unsigned Index) const { + DataRefImpl DRI; + DRI.d.a = Index; + return getSectionRelBegin(DRI); +} + +relocation_iterator MachOObjectFile::getSectionRelEnd(unsigned Index) const { + DataRefImpl DRI; + DRI.d.a = Index; + return getSectionRelEnd(DRI); +} + StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { ArrayRef Raw = getSectionRawFinalSegmentName(Sec); @@ -1375,6 +1423,18 @@ macho::Section64 MachOObjectFile::getSection64(DataRefImpl DRI) const { return getStruct(this, Sections[DRI.d.a]); } +macho::Section MachOObjectFile::getSection(const LoadCommandInfo &L, + unsigned Index) const { + const char *Sec = getSectionPtr(this, L, Index); + return getStruct(this, Sec); +} + +macho::Section64 MachOObjectFile::getSection64(const LoadCommandInfo &L, + unsigned Index) const { + const char *Sec = getSectionPtr(this, L, Index); + return getStruct(this, Sec); +} + macho::SymbolTableEntry MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { const char *P = reinterpret_cast(DRI.p); @@ -1392,6 +1452,21 @@ MachOObjectFile::getLinkeditDataLoadCommand(const MachOObjectFile::LoadCommandIn return getStruct(this, L.Ptr); } +macho::SegmentLoadCommand +MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +macho::Segment64LoadCommand +MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +macho::LinkerOptionsLoadCommand +MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + macho::RelocationEntry MachOObjectFile::getRelocation(DataRefImpl Rel) const { const char *P = reinterpret_cast(Rel.p); @@ -1402,11 +1477,39 @@ macho::Header MachOObjectFile::getHeader() const { return getStruct(this, getPtr(this, 0)); } -macho::SymtabLoadCommand -MachOObjectFile::getSymtabLoadCommand() const { +macho::Header64Ext MachOObjectFile::getHeader64Ext() const { + return + getStruct(this, getPtr(this, sizeof(macho::Header))); +} + +macho::IndirectSymbolTableEntry MachOObjectFile::getIndirectSymbolTableEntry( + const macho::DysymtabLoadCommand &DLC, + unsigned Index) const { + uint64_t Offset = DLC.IndirectSymbolTableOffset + + Index * sizeof(macho::IndirectSymbolTableEntry); + return getStruct(this, getPtr(this, Offset)); +} + +macho::DataInCodeTableEntry +MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, + unsigned Index) const { + uint64_t Offset = DataOffset + Index * sizeof(macho::DataInCodeTableEntry); + return getStruct(this, getPtr(this, Offset)); +} + +macho::SymtabLoadCommand MachOObjectFile::getSymtabLoadCommand() const { return getStruct(this, SymtabLoadCmd); } +macho::DysymtabLoadCommand MachOObjectFile::getDysymtabLoadCommand() const { + return getStruct(this, DysymtabLoadCmd); +} + +StringRef MachOObjectFile::getStringTableData() const { + macho::SymtabLoadCommand S = getSymtabLoadCommand(); + return getData().substr(S.StringTableOffset, S.StringTableSize); +} + bool MachOObjectFile::is64Bit() const { return getType() == getMachOType(false, true) || getType() == getMachOType(true, true); diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 4d8d345894..ead541a5b8 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -17,7 +17,7 @@ #include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Memory.h" diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index 3bd3ecc8fd..88fd4529ab 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Object/MachOObject.h" +#include "llvm/Object/MachO.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" @@ -66,7 +67,8 @@ static void DumpSegmentCommandData(StringRef Name, outs() << " ('flags', " << Flags << ")\n"; } -static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, +static int DumpSectionData(const MachOObjectFile &Obj, unsigned Index, + StringRef Name, StringRef SegmentName, uint64_t Address, uint64_t Size, uint32_t Offset, uint32_t Align, uint32_t RelocationTableOffset, @@ -92,26 +94,22 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, outs() << " ),\n"; // Dump the relocation entries. - int Res = 0; outs() << " ('_relocations', [\n"; - for (unsigned i = 0; i != NumRelocationTableEntries; ++i) { - InMemoryStruct RE; - Obj.ReadRelocationEntry(RelocationTableOffset, i, RE); - if (!RE) { - Res = Error("unable to read relocation table entry '" + Twine(i) + "'"); - break; - } - - outs() << " # Relocation " << i << "\n"; - outs() << " (('word-0', " << format("0x%x", RE->Word0) << "),\n"; - outs() << " ('word-1', " << format("0x%x", RE->Word1) << ")),\n"; + unsigned RelNum = 0; + error_code EC; + for (relocation_iterator I = Obj.getSectionRelBegin(Index), + E = Obj.getSectionRelEnd(Index); I != E; I.increment(EC), ++RelNum) { + macho::RelocationEntry RE = Obj.getRelocation(I->getRawDataRefImpl()); + outs() << " # Relocation " << RelNum << "\n"; + outs() << " (('word-0', " << format("0x%x", RE.Word0) << "),\n"; + outs() << " ('word-1', " << format("0x%x", RE.Word1) << ")),\n"; } outs() << " ])\n"; // Dump the section data, if requested. if (ShowSectionData) { outs() << " ('_section_data', '"; - StringRef Data = Obj.getData(Offset, Size); + StringRef Data = Obj.getData().substr(Offset, Size); for (unsigned i = 0; i != Data.size(); ++i) { if (i && (i % 4) == 0) outs() << ' '; @@ -121,208 +119,162 @@ static int DumpSectionData(MachOObject &Obj, unsigned Index, StringRef Name, outs() << "')\n"; } - return Res; + return 0; } -static int DumpSegmentCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct SLC; - Obj.ReadSegmentLoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); +static int DumpSegmentCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::SegmentLoadCommand SLC = Obj.getSegmentLoadCommand(LCI); - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, - SLC->VMSize, SLC->FileOffset, SLC->FileSize, - SLC->MaxVMProtection, SLC->InitialVMProtection, - SLC->NumSections, SLC->Flags); + DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, + SLC.VMSize, SLC.FileOffset, SLC.FileSize, + SLC.MaxVMProtection, SLC.InitialVMProtection, + SLC.NumSections, SLC.Flags); // Dump the sections. - int Res = 0; outs() << " ('sections', [\n"; - for (unsigned i = 0; i != SLC->NumSections; ++i) { - InMemoryStruct Sect; - Obj.ReadSection(LCI, i, Sect); - if (!SLC) { - Res = Error("unable to read section '" + Twine(i) + "'"); - break; - } - - if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), - StringRef(Sect->SegmentName, 16), Sect->Address, - Sect->Size, Sect->Offset, Sect->Align, - Sect->RelocationTableOffset, - Sect->NumRelocationTableEntries, Sect->Flags, - Sect->Reserved1, Sect->Reserved2))) - break; + for (unsigned i = 0; i != SLC.NumSections; ++i) { + macho::Section Sect = Obj.getSection(LCI, i); + DumpSectionData(Obj, i, StringRef(Sect.Name, 16), + StringRef(Sect.SegmentName, 16), Sect.Address, + Sect.Size, Sect.Offset, Sect.Align, + Sect.RelocationTableOffset, + Sect.NumRelocationTableEntries, Sect.Flags, + Sect.Reserved1, Sect.Reserved2); } outs() << " ])\n"; - return Res; + return 0; } -static int DumpSegment64Command(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct SLC; - Obj.ReadSegment64LoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); - - DumpSegmentCommandData(StringRef(SLC->Name, 16), SLC->VMAddress, - SLC->VMSize, SLC->FileOffset, SLC->FileSize, - SLC->MaxVMProtection, SLC->InitialVMProtection, - SLC->NumSections, SLC->Flags); +static int DumpSegment64Command(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::Segment64LoadCommand SLC = Obj.getSegment64LoadCommand(LCI); + DumpSegmentCommandData(StringRef(SLC.Name, 16), SLC.VMAddress, + SLC.VMSize, SLC.FileOffset, SLC.FileSize, + SLC.MaxVMProtection, SLC.InitialVMProtection, + SLC.NumSections, SLC.Flags); // Dump the sections. - int Res = 0; outs() << " ('sections', [\n"; - for (unsigned i = 0; i != SLC->NumSections; ++i) { - InMemoryStruct Sect; - Obj.ReadSection64(LCI, i, Sect); - if (!SLC) { - Res = Error("unable to read section '" + Twine(i) + "'"); - break; - } - - if ((Res = DumpSectionData(Obj, i, StringRef(Sect->Name, 16), - StringRef(Sect->SegmentName, 16), Sect->Address, - Sect->Size, Sect->Offset, Sect->Align, - Sect->RelocationTableOffset, - Sect->NumRelocationTableEntries, Sect->Flags, - Sect->Reserved1, Sect->Reserved2, - Sect->Reserved3))) - break; + for (unsigned i = 0; i != SLC.NumSections; ++i) { + macho::Section64 Sect = Obj.getSection64(LCI, i); + + DumpSectionData(Obj, i, StringRef(Sect.Name, 16), + StringRef(Sect.SegmentName, 16), Sect.Address, + Sect.Size, Sect.Offset, Sect.Align, + Sect.RelocationTableOffset, + Sect.NumRelocationTableEntries, Sect.Flags, + Sect.Reserved1, Sect.Reserved2, + Sect.Reserved3); } outs() << " ])\n"; - return Res; + return 0; } -static void DumpSymbolTableEntryData(MachOObject &Obj, +static void DumpSymbolTableEntryData(const MachOObjectFile &Obj, unsigned Index, uint32_t StringIndex, uint8_t Type, uint8_t SectionIndex, - uint16_t Flags, uint64_t Value) { + uint16_t Flags, uint64_t Value, + StringRef StringTable) { + const char *Name = &StringTable.data()[StringIndex]; outs() << " # Symbol " << Index << "\n"; outs() << " (('n_strx', " << StringIndex << ")\n"; outs() << " ('n_type', " << format("0x%x", Type) << ")\n"; outs() << " ('n_sect', " << uint32_t(SectionIndex) << ")\n"; outs() << " ('n_desc', " << Flags << ")\n"; outs() << " ('n_value', " << Value << ")\n"; - outs() << " ('_string', '" << Obj.getStringAtIndex(StringIndex) << "')\n"; + outs() << " ('_string', '" << Name << "')\n"; outs() << " ),\n"; } -static int DumpSymtabCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct SLC; - Obj.ReadSymtabLoadCommand(LCI, SLC); - if (!SLC) - return Error("unable to read segment load command"); - - outs() << " ('symoff', " << SLC->SymbolTableOffset << ")\n"; - outs() << " ('nsyms', " << SLC->NumSymbolTableEntries << ")\n"; - outs() << " ('stroff', " << SLC->StringTableOffset << ")\n"; - outs() << " ('strsize', " << SLC->StringTableSize << ")\n"; +static int DumpSymtabCommand(const MachOObjectFile &Obj) { + macho::SymtabLoadCommand SLC = Obj.getSymtabLoadCommand(); - // Cache the string table data. - Obj.RegisterStringTable(*SLC); + outs() << " ('symoff', " << SLC.SymbolTableOffset << ")\n"; + outs() << " ('nsyms', " << SLC.NumSymbolTableEntries << ")\n"; + outs() << " ('stroff', " << SLC.StringTableOffset << ")\n"; + outs() << " ('strsize', " << SLC.StringTableSize << ")\n"; // Dump the string data. outs() << " ('_string_data', '"; - outs().write_escaped(Obj.getStringTableData(), + StringRef StringTable = Obj.getStringTableData(); + outs().write_escaped(StringTable, /*UseHexEscapes=*/true) << "')\n"; // Dump the symbol table. - int Res = 0; outs() << " ('_symbols', [\n"; - for (unsigned i = 0; i != SLC->NumSymbolTableEntries; ++i) { + error_code EC; + unsigned SymNum = 0; + for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + I.increment(EC), ++SymNum) { + DataRefImpl DRI = I->getRawDataRefImpl(); if (Obj.is64Bit()) { - InMemoryStruct STE; - Obj.ReadSymbol64TableEntry(SLC->SymbolTableOffset, i, STE); - if (!STE) { - Res = Error("unable to read symbol: '" + Twine(i) + "'"); - break; - } - - DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, - STE->SectionIndex, STE->Flags, STE->Value); + macho::Symbol64TableEntry STE = Obj.getSymbol64TableEntry(DRI); + DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, + STE.SectionIndex, STE.Flags, STE.Value, + StringTable); } else { - InMemoryStruct STE; - Obj.ReadSymbolTableEntry(SLC->SymbolTableOffset, i, STE); - if (!SLC) { - Res = Error("unable to read symbol: '" + Twine(i) + "'"); - break; - } - - DumpSymbolTableEntryData(Obj, i, STE->StringIndex, STE->Type, - STE->SectionIndex, STE->Flags, STE->Value); + macho::SymbolTableEntry STE = Obj.getSymbolTableEntry(DRI); + DumpSymbolTableEntryData(Obj, SymNum, STE.StringIndex, STE.Type, + STE.SectionIndex, STE.Flags, STE.Value, + StringTable); } } outs() << " ])\n"; - return Res; + return 0; } -static int DumpDysymtabCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct DLC; - Obj.ReadDysymtabLoadCommand(LCI, DLC); - if (!DLC) - return Error("unable to read segment load command"); - - outs() << " ('ilocalsym', " << DLC->LocalSymbolsIndex << ")\n"; - outs() << " ('nlocalsym', " << DLC->NumLocalSymbols << ")\n"; - outs() << " ('iextdefsym', " << DLC->ExternalSymbolsIndex << ")\n"; - outs() << " ('nextdefsym', " << DLC->NumExternalSymbols << ")\n"; - outs() << " ('iundefsym', " << DLC->UndefinedSymbolsIndex << ")\n"; - outs() << " ('nundefsym', " << DLC->NumUndefinedSymbols << ")\n"; - outs() << " ('tocoff', " << DLC->TOCOffset << ")\n"; - outs() << " ('ntoc', " << DLC->NumTOCEntries << ")\n"; - outs() << " ('modtaboff', " << DLC->ModuleTableOffset << ")\n"; - outs() << " ('nmodtab', " << DLC->NumModuleTableEntries << ")\n"; - outs() << " ('extrefsymoff', " << DLC->ReferenceSymbolTableOffset << ")\n"; +static int DumpDysymtabCommand(const MachOObjectFile &Obj) { + macho::DysymtabLoadCommand DLC = Obj.getDysymtabLoadCommand(); + + outs() << " ('ilocalsym', " << DLC.LocalSymbolsIndex << ")\n"; + outs() << " ('nlocalsym', " << DLC.NumLocalSymbols << ")\n"; + outs() << " ('iextdefsym', " << DLC.ExternalSymbolsIndex << ")\n"; + outs() << " ('nextdefsym', " << DLC.NumExternalSymbols << ")\n"; + outs() << " ('iundefsym', " << DLC.UndefinedSymbolsIndex << ")\n"; + outs() << " ('nundefsym', " << DLC.NumUndefinedSymbols << ")\n"; + outs() << " ('tocoff', " << DLC.TOCOffset << ")\n"; + outs() << " ('ntoc', " << DLC.NumTOCEntries << ")\n"; + outs() << " ('modtaboff', " << DLC.ModuleTableOffset << ")\n"; + outs() << " ('nmodtab', " << DLC.NumModuleTableEntries << ")\n"; + outs() << " ('extrefsymoff', " << DLC.ReferenceSymbolTableOffset << ")\n"; outs() << " ('nextrefsyms', " - << DLC->NumReferencedSymbolTableEntries << ")\n"; - outs() << " ('indirectsymoff', " << DLC->IndirectSymbolTableOffset << ")\n"; + << DLC.NumReferencedSymbolTableEntries << ")\n"; + outs() << " ('indirectsymoff', " << DLC.IndirectSymbolTableOffset << ")\n"; outs() << " ('nindirectsyms', " - << DLC->NumIndirectSymbolTableEntries << ")\n"; - outs() << " ('extreloff', " << DLC->ExternalRelocationTableOffset << ")\n"; - outs() << " ('nextrel', " << DLC->NumExternalRelocationTableEntries << ")\n"; - outs() << " ('locreloff', " << DLC->LocalRelocationTableOffset << ")\n"; - outs() << " ('nlocrel', " << DLC->NumLocalRelocationTableEntries << ")\n"; + << DLC.NumIndirectSymbolTableEntries << ")\n"; + outs() << " ('extreloff', " << DLC.ExternalRelocationTableOffset << ")\n"; + outs() << " ('nextrel', " << DLC.NumExternalRelocationTableEntries << ")\n"; + outs() << " ('locreloff', " << DLC.LocalRelocationTableOffset << ")\n"; + outs() << " ('nlocrel', " << DLC.NumLocalRelocationTableEntries << ")\n"; // Dump the indirect symbol table. - int Res = 0; outs() << " ('_indirect_symbols', [\n"; - for (unsigned i = 0; i != DLC->NumIndirectSymbolTableEntries; ++i) { - InMemoryStruct ISTE; - Obj.ReadIndirectSymbolTableEntry(*DLC, i, ISTE); - if (!ISTE) { - Res = Error("unable to read segment load command"); - break; - } - + for (unsigned i = 0; i != DLC.NumIndirectSymbolTableEntries; ++i) { + macho::IndirectSymbolTableEntry ISTE = + Obj.getIndirectSymbolTableEntry(DLC, i); outs() << " # Indirect Symbol " << i << "\n"; outs() << " (('symbol_index', " - << format("0x%x", ISTE->Index) << "),),\n"; + << format("0x%x", ISTE.Index) << "),),\n"; } outs() << " ])\n"; - return Res; + return 0; } -static int DumpLinkeditDataCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct LLC; - Obj.ReadLinkeditDataLoadCommand(LCI, LLC); - if (!LLC) - return Error("unable to read segment load command"); - - outs() << " ('dataoff', " << LLC->DataOffset << ")\n" - << " ('datasize', " << LLC->DataSize << ")\n" +static int +DumpLinkeditDataCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); + outs() << " ('dataoff', " << LLC.DataOffset << ")\n" + << " ('datasize', " << LLC.DataSize << ")\n" << " ('_addresses', [\n"; SmallVector Addresses; - Obj.ReadULEB128s(LLC->DataOffset, Addresses); + Obj.ReadULEB128s(LLC.DataOffset, Addresses); for (unsigned i = 0, e = Addresses.size(); i != e; ++i) outs() << " # Address " << i << '\n' << " ('address', " << format("0x%x", Addresses[i]) << "),\n"; @@ -332,28 +284,22 @@ static int DumpLinkeditDataCommand(MachOObject &Obj, return 0; } -static int DumpDataInCodeDataCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct LLC; - Obj.ReadLinkeditDataLoadCommand(LCI, LLC); - if (!LLC) - return Error("unable to read data-in-code load command"); - - outs() << " ('dataoff', " << LLC->DataOffset << ")\n" - << " ('datasize', " << LLC->DataSize << ")\n" +static int +DumpDataInCodeDataCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkeditDataLoadCommand LLC = Obj.getLinkeditDataLoadCommand(LCI); + outs() << " ('dataoff', " << LLC.DataOffset << ")\n" + << " ('datasize', " << LLC.DataSize << ")\n" << " ('_data_regions', [\n"; - - unsigned NumRegions = LLC->DataSize / 8; + unsigned NumRegions = LLC.DataSize / 8; for (unsigned i = 0; i < NumRegions; ++i) { - InMemoryStruct DICE; - Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE); - if (!DICE) - return Error("unable to read DataInCodeTableEntry"); + macho::DataInCodeTableEntry DICE = + Obj.getDataInCodeTableEntry(LLC.DataOffset, i); outs() << " # DICE " << i << "\n" - << " ('offset', " << DICE->Offset << ")\n" - << " ('length', " << DICE->Length << ")\n" - << " ('kind', " << DICE->Kind << ")\n"; + << " ('offset', " << DICE.Offset << ")\n" + << " ('length', " << DICE.Length << ")\n" + << " ('kind', " << DICE.Kind << ")\n"; } outs() <<" ])\n"; @@ -361,99 +307,111 @@ static int DumpDataInCodeDataCommand(MachOObject &Obj, return 0; } -static int DumpLinkerOptionsCommand(MachOObject &Obj, - const MachOObject::LoadCommandInfo &LCI) { - InMemoryStruct LOLC; - Obj.ReadLinkerOptionsLoadCommand(LCI, LOLC); - if (!LOLC) - return Error("unable to read linker options load command"); - - outs() << " ('count', " << LOLC->Count << ")\n" - << " ('_strings', [\n"; - - uint64_t DataSize = LOLC->Size - sizeof(macho::LinkerOptionsLoadCommand); - StringRef Data = Obj.getData( - LCI.Offset + sizeof(macho::LinkerOptionsLoadCommand), DataSize); - for (unsigned i = 0; i != LOLC->Count; ++i) { - std::pair Split = Data.split('\0'); - outs() << "\t\""; - outs().write_escaped(Split.first); - outs() << "\",\n"; - Data = Split.second; - } - outs() <<" ])\n"; +static int +DumpLinkerOptionsCommand(const MachOObjectFile &Obj, + const MachOObjectFile::LoadCommandInfo &LCI) { + macho::LinkerOptionsLoadCommand LOLC = Obj.getLinkerOptionsLoadCommand(LCI); + outs() << " ('count', " << LOLC.Count << ")\n" + << " ('_strings', [\n"; + + uint64_t DataSize = LOLC.Size - sizeof(macho::LinkerOptionsLoadCommand); + const char *P = LCI.Ptr + sizeof(macho::LinkerOptionsLoadCommand); + StringRef Data(P, DataSize); + for (unsigned i = 0; i != LOLC.Count; ++i) { + std::pair Split = Data.split('\0'); + outs() << "\t\""; + outs().write_escaped(Split.first); + outs() << "\",\n"; + Data = Split.second; + } + outs() <<" ])\n"; return 0; } - -static int DumpLoadCommand(MachOObject &Obj, unsigned Index) { - const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index); - int Res = 0; - - outs() << " # Load Command " << Index << "\n" - << " (('command', " << LCI.Command.Type << ")\n" - << " ('size', " << LCI.Command.Size << ")\n"; - switch (LCI.Command.Type) { +static int DumpLoadCommand(const MachOObjectFile &Obj, + MachOObjectFile::LoadCommandInfo &LCI) { + switch (LCI.C.Type) { case macho::LCT_Segment: - Res = DumpSegmentCommand(Obj, LCI); - break; + return DumpSegmentCommand(Obj, LCI); case macho::LCT_Segment64: - Res = DumpSegment64Command(Obj, LCI); - break; + return DumpSegment64Command(Obj, LCI); case macho::LCT_Symtab: - Res = DumpSymtabCommand(Obj, LCI); - break; + return DumpSymtabCommand(Obj); case macho::LCT_Dysymtab: - Res = DumpDysymtabCommand(Obj, LCI); - break; + return DumpDysymtabCommand(Obj); case macho::LCT_CodeSignature: case macho::LCT_SegmentSplitInfo: case macho::LCT_FunctionStarts: - Res = DumpLinkeditDataCommand(Obj, LCI); - break; + return DumpLinkeditDataCommand(Obj, LCI); case macho::LCT_DataInCode: - Res = DumpDataInCodeDataCommand(Obj, LCI); - break; + return DumpDataInCodeDataCommand(Obj, LCI); case macho::LCT_LinkerOptions: - Res = DumpLinkerOptionsCommand(Obj, LCI); - break; + return DumpLinkerOptionsCommand(Obj, LCI); default: - Warning("unknown load command: " + Twine(LCI.Command.Type)); - break; + Warning("unknown load command: " + Twine(LCI.C.Type)); + return 0; } - outs() << " ),\n"; +} + +static int DumpLoadCommand(const MachOObjectFile &Obj, unsigned Index, + MachOObjectFile::LoadCommandInfo &LCI) { + outs() << " # Load Command " << Index << "\n" + << " (('command', " << LCI.C.Type << ")\n" + << " ('size', " << LCI.C.Size << ")\n"; + int Res = DumpLoadCommand(Obj, LCI); + outs() << " ),\n"; return Res; } +static void printHeader(const MachOObjectFile *Obj, + const macho::Header &Header) { + outs() << "('cputype', " << Header.CPUType << ")\n"; + outs() << "('cpusubtype', " << Header.CPUSubtype << ")\n"; + outs() << "('filetype', " << Header.FileType << ")\n"; + outs() << "('num_load_commands', " << Header.NumLoadCommands << ")\n"; + outs() << "('load_commands_size', " << Header.SizeOfLoadCommands << ")\n"; + outs() << "('flag', " << Header.Flags << ")\n"; + + // Print extended header if 64-bit. + if (Obj->is64Bit()) { + macho::Header64Ext Header64Ext = Obj->getHeader64Ext(); + outs() << "('reserved', " << Header64Ext.Reserved << ")\n"; + } +} + int main(int argc, char **argv) { ProgramName = argv[0]; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); - // Load the input file. - std::string ErrorStr; - OwningPtr InputBuffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); + OwningPtr Binary; + if (error_code EC = createBinary(InputFile, Binary)) + return Error("unable to read input: '" + EC.message() + "'"); - // Construct the Mach-O wrapper object. - OwningPtr InputObject( - MachOObject::LoadFromBuffer(InputBuffer.take(), &ErrorStr)); + const MachOObjectFile *InputObject = dyn_cast(Binary.get()); if (!InputObject) - return Error("unable to load object: '" + ErrorStr + "'"); + return Error("Not a MachO object"); // Print the header - InputObject->printHeader(outs()); + macho::Header Header = InputObject->getHeader(); + printHeader(InputObject, Header); // Print the load commands. int Res = 0; + MachOObjectFile::LoadCommandInfo Command = + InputObject->getFirstLoadCommandInfo(); outs() << "('load_commands', [\n"; - for (unsigned i = 0; i != InputObject->getHeader().NumLoadCommands; ++i) - if ((Res = DumpLoadCommand(*InputObject, i))) + for (unsigned i = 0; ; ++i) { + if (DumpLoadCommand(*InputObject, i, Command)) break; + + if (i == Header.NumLoadCommands - 1) + break; + Command = InputObject->getNextLoadCommandInfo(Command); + } outs() << "])\n"; return Res; -- cgit v1.2.3-70-g09d2 From 59a0e79631ed851d98cf9c2ba6fa5f9aafdfdc93 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Mon, 29 Apr 2013 22:24:22 +0000 Subject: Add getSymbolAlignment to the ObjectFile interface. For regular object files this is only meaningful for common symbols. An object file format with direct support for atoms should be able to provide alignment information for all symbols. This replaces getCommonSymbolAlignment and fixes test-common-symbols-alignment.ll on darwin. This also includes a fix to MachOObjectFile::getSymbolFlags. It was marking undefined symbols as common (already tested by existing mcjit tests now that it is used). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180736 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 16 ++++++++++++++++ include/llvm/Object/MachO.h | 1 + include/llvm/Object/ObjectFile.h | 7 +++++++ lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 3 ++- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 7 ------- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 3 --- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 7 ------- lib/Object/MachOObjectFile.cpp | 21 +++++++++++++++++++-- lib/Object/ObjectFile.cpp | 6 ++++++ .../MCJIT/test-common-symbols-alignment.ll | 1 - 10 files changed, 51 insertions(+), 21 deletions(-) (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 4f0e5b8db8..b36460ca52 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -682,6 +682,7 @@ protected: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolNMTypeChar(DataRefImpl Symb, char &Res) const; virtual error_code getSymbolFlags(DataRefImpl Symb, uint32_t &Res) const; @@ -1114,6 +1115,21 @@ error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, } } +template +error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, + uint32_t &Res) const { + uint32_t flags; + getSymbolFlags(Symb, flags); + if (flags & SymbolRef::SF_Common) { + uint64_t Value; + getSymbolValue(Symb, Value); + Res = Value; + } else { + Res = 0; + } + return object_error::success; +} + template error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, uint64_t &Result) const { diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 98d3788e44..17a8fc2bff 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -39,6 +39,7 @@ public: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index cbe7ec92d3..eb53cc0aab 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -217,6 +217,8 @@ public: /// mapped). error_code getAddress(uint64_t &Result) const; error_code getFileOffset(uint64_t &Result) const; + /// @brief Get the alignment of this symbol as the actual value (not log 2). + error_code getAlignment(uint32_t &Result) const; error_code getSize(uint64_t &Result) const; error_code getType(SymbolRef::Type &Result) const; @@ -292,6 +294,7 @@ protected: virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0; virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0; + virtual error_code getSymbolAlignment(DataRefImpl Symb, uint32_t &Res) const; virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0; virtual error_code getSymbolType(DataRefImpl Symb, SymbolRef::Type &Res) const = 0; @@ -425,6 +428,10 @@ inline error_code SymbolRef::getFileOffset(uint64_t &Result) const { return OwningObject->getSymbolFileOffset(SymbolPimpl, Result); } +inline error_code SymbolRef::getAlignment(uint32_t &Result) const { + return OwningObject->getSymbolAlignment(SymbolPimpl, Result); +} + inline error_code SymbolRef::getSize(uint64_t &Result) const { return OwningObject->getSymbolSize(SymbolPimpl, Result); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 354795dc5f..7b32db7f0e 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -96,7 +96,8 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { bool isCommon = flags & SymbolRef::SF_Common; if (isCommon) { // Add the common symbols to a list. We'll allocate them all below. - uint64_t Align = getCommonSymbolAlignment(*i); + uint32_t Align; + Check(i->getAlignment(Align)); uint64_t Size = 0; Check(i->getSize(Size)); CommonSize += Size + Align; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index ef4a4050e9..c5bad8e416 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -848,13 +848,6 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID, } } -unsigned RuntimeDyldELF::getCommonSymbolAlignment(const SymbolRef &Sym) { - // In ELF, the value of an SHN_COMMON symbol is its alignment requirement. - uint64_t Align; - Check(Sym.getValue(Align)); - return Align; -} - bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) return false; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index b6ddf2d6a7..102b1c6b59 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -68,9 +68,6 @@ class RuntimeDyldELF : public RuntimeDyldImpl { int64_t Addend); - unsigned getCommonSymbolAlignment(const SymbolRef &Sym); - - uint64_t findPPC64TOC() const; void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 3211a1c7ea..51873b1f4b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -194,13 +194,6 @@ protected: return (uint8_t*)Sections[SectionID].Address; } - // Subclasses can override this method to get the alignment requirement of - // a common symbol. Returns no alignment requirement if not implemented. - virtual unsigned getCommonSymbolAlignment(const SymbolRef &Sym) { - return 0; - } - - void writeInt16BE(uint8_t *Addr, uint16_t Value) { if (sys::IsLittleEndianHost) Value = sys::SwapByteOrder(Value); diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index bb6ca93176..f6840b8c15 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -495,6 +495,19 @@ MachOObjectFile::getSymbolFileOffset(DataRefImpl Symb, return object_error::success; } +error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { + uint32_t flags; + this->getSymbolFlags(DRI, flags); + if (flags & SymbolRef::SF_Common) { + SymbolTableEntryBase Entry = getSymbolTableEntryBase(this, DRI); + Result = 1 << MachO::GET_COMM_ALIGN(Entry.Flags); + } else { + Result = 0; + } + return object_error::success; +} + error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, uint64_t &Result) const { uint64_t BeginOffset; @@ -609,8 +622,12 @@ error_code MachOObjectFile::getSymbolFlags(DataRefImpl DRI, if (MachOType & MachO::NlistMaskExternal) { Result |= SymbolRef::SF_Global; - if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) - Result |= SymbolRef::SF_Common; + if ((MachOType & MachO::NlistMaskType) == MachO::NListTypeUndefined) { + uint64_t Value; + getSymbolAddress(DRI, Value); + if (Value) + Result |= SymbolRef::SF_Common; + } } if (MachOFlags & (MachO::NListDescWeakRef | MachO::NListDescWeakDef)) diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index 518959aa05..77fd995cf0 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -27,6 +27,12 @@ ObjectFile::ObjectFile(unsigned int Type, MemoryBuffer *source) : Binary(Type, source) { } +error_code ObjectFile::getSymbolAlignment(DataRefImpl DRI, + uint32_t &Result) const { + Result = 0; + return object_error::success; +} + ObjectFile *ObjectFile::createObjectFile(MemoryBuffer *Object) { if (!Object || Object->getBufferSize() < 64) return 0; diff --git a/test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll b/test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll index 43256c4492..989a473423 100644 --- a/test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll +++ b/test/ExecutionEngine/MCJIT/test-common-symbols-alignment.ll @@ -1,5 +1,4 @@ ; RUN: %lli_mcjit -O0 %s -; XFAIL: darwin ; This test checks that common symbols have been allocated addresses honouring ; the alignment requirement. -- cgit v1.2.3-70-g09d2 From e87dadc44b1544c35e13cf48dfe167109929a944 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 30 Apr 2013 15:40:54 +0000 Subject: Fix Addend computation for non external relocations on Macho. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@180790 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/MachO.h | 1 + .../RuntimeDyld/RuntimeDyldMachO.cpp | 38 ++++++---------------- lib/Object/MachOObjectFile.cpp | 10 ++++++ test/ExecutionEngine/MCJIT/non-extern-addend.ll | 12 +++++++ 4 files changed, 33 insertions(+), 28 deletions(-) create mode 100644 test/ExecutionEngine/MCJIT/non-extern-addend.ll (limited to 'lib/Object/MachOObjectFile.cpp') diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 17a8fc2bff..14cd4d767d 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -130,6 +130,7 @@ public: unsigned getAnyRelocationPCRel(const macho::RelocationEntry &RE) const; unsigned getAnyRelocationLength(const macho::RelocationEntry &RE) const; unsigned getAnyRelocationType(const macho::RelocationEntry &RE) const; + SectionRef getRelocationSection(const macho::RelocationEntry &RE) const; // Walk load commands. LoadCommandInfo getFirstLoadCommandInfo() const; diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 6054b2ab79..b3467a9ab3 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -232,12 +232,12 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, unsigned Size = MachO->getAnyRelocationLength(RE); uint64_t Offset; RelI.getOffset(Offset); - if (isExtern) { - uint8_t *LocalAddress = Section.Address + Offset; - unsigned NumBytes = 1 << Size; - uint64_t Addend = 0; - memcpy(&Addend, LocalAddress, NumBytes); + uint8_t *LocalAddress = Section.Address + Offset; + unsigned NumBytes = 1 << Size; + uint64_t Addend = 0; + memcpy(&Addend, LocalAddress, NumBytes); + if (isExtern) { // Obtain the symbol name which is referenced in the relocation SymbolRef Symbol; RelI.getSymbol(Symbol); @@ -260,29 +260,11 @@ void RuntimeDyldMachO::processRelocationRef(unsigned SectionID, } } } else { - error_code err; - uint8_t sectionIndex = static_cast(RelType & 0xFF); - section_iterator si = Obj.begin_sections(), - se = Obj.end_sections(); - for (uint8_t i = 1; i < sectionIndex; i++) { - error_code err; - si.increment(err); - if (si == se) - break; - } - assert(si != se && "No section containing relocation!"); - Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID); - Value.Addend = 0; - // FIXME: The size and type of the relocation determines if we can - // encode an Addend in the target location itself, and if so, how many - // bytes we should read in order to get it. We don't yet support doing - // that, and just assuming it's sizeof(intptr_t) is blatantly wrong. - //Value.Addend = *(const intptr_t *)Target; - if (Value.Addend) { - // The MachO addend is an offset from the current section. We need it - // to be an offset from the destination section - Value.Addend += Section.ObjAddress - Sections[Value.SectionID].ObjAddress; - } + SectionRef Sec = MachO->getRelocationSection(RE); + Value.SectionID = findOrEmitSection(Obj, Sec, true, ObjSectionToID); + uint64_t Addr; + Sec.getAddress(Addr); + Value.Addend = Addend - Addr; } if (Arch == Triple::arm && (RelType & 0xf) == macho::RIT_ARM_Branch24Bit) { diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index f6840b8c15..dfd8d3d3dd 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -1414,6 +1414,16 @@ MachOObjectFile::getAnyRelocationType(const macho::RelocationEntry &RE) const { return getPlainRelocationType(this, RE); } +SectionRef +MachOObjectFile::getRelocationSection(const macho::RelocationEntry &RE) const { + if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) + return *end_sections(); + unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; + DataRefImpl DRI; + DRI.d.a = SecNum; + return SectionRef(DRI, this); +} + MachOObjectFile::LoadCommandInfo MachOObjectFile::getFirstLoadCommandInfo() const { MachOObjectFile::LoadCommandInfo Load; diff --git a/test/ExecutionEngine/MCJIT/non-extern-addend.ll b/test/ExecutionEngine/MCJIT/non-extern-addend.ll new file mode 100644 index 0000000000..3a6e634412 --- /dev/null +++ b/test/ExecutionEngine/MCJIT/non-extern-addend.ll @@ -0,0 +1,12 @@ +; RUN: %lli_mcjit %s > /dev/null + +define i32 @foo(i32 %X, i32 %Y, double %A) { + %cond212 = fcmp ueq double %A, 2.000000e+00 ; [#uses=1] + %cast110 = zext i1 %cond212 to i32 ; [#uses=1] + ret i32 %cast110 +} + +define i32 @main() { + %reg212 = call i32 @foo( i32 0, i32 1, double 1.000000e+00 ) ; [#uses=1] + ret i32 %reg212 +} -- cgit v1.2.3-70-g09d2