diff options
| author | Nick Kledzik <kledzik@apple.com> | 2014-05-29 20:44:21 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2014-05-29 20:44:21 +0000 |
| commit | 9ede702bc4ef97df625c0e69be225f1fd5a6a55c (patch) | |
| tree | 82c81a981efae2eeda64d2917ecbb07fc145d615 /lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | |
| parent | c6b506a0ae3bf1e6902f2fe83b62ed945a8c30e0 (diff) | |
| download | bcm5719-llvm-9ede702bc4ef97df625c0e69be225f1fd5a6a55c.tar.gz bcm5719-llvm-9ede702bc4ef97df625c0e69be225f1fd5a6a55c.zip | |
[mach-o] Add support for parsing CFString sections
llvm-svn: 209844
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 4a8d4b79118..c06289a1061 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -87,8 +87,12 @@ static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, const Section §ion = normalizedFile.sections[sym.sect - 1]; uint64_t offset = sym.value - section.address; uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value; - if (section.type == llvm::MachO::S_ZEROFILL){ + if (section.type == llvm::MachO::S_ZEROFILL) { file.addZeroFillDefinedAtom(sym.name, atomScope(sym.scope), size, copyRefs); + } + else if ((section.type == llvm::MachO::S_CSTRING_LITERALS) && + (sym.name[0] == 'L')) { + // Ignore L labels on cstrings. } else { ArrayRef<uint8_t> atomContent = section.content.slice(offset, size); DefinedAtom::Merge m = DefinedAtom::mergeNo; @@ -111,37 +115,72 @@ static void processUndefindeSymbol(MachOFile &file, const Symbol &sym, } } +// A __TEXT/__ustring section contains UTF16 strings. Atom boundaries are +// determined by finding the terminating 0x0000 in each string. +static error_code processUTF16Section(MachOFile &file, const Section §ion, + bool is64, bool copyRefs) { + if ((section.content.size() % 4) != 0) + return make_dynamic_error_code(Twine("Section ") + section.segmentName + + "/" + section.sectionName + + " has a size that is not even"); + unsigned offset = 0; + for (size_t i = 0, e = section.content.size(); i != e; i +=2) { + if ((section.content[i] == 0) && (section.content[i+1] == 0)) { + unsigned size = i - offset + 2; + ArrayRef<uint8_t> utf16Content = section.content.slice(offset, size); + file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit, + DefinedAtom::typeUTF16String, + DefinedAtom::mergeByContent, utf16Content, + copyRefs); + offset = i + 2; + } + } + if (offset != section.content.size()) { + return make_dynamic_error_code(Twine("Section ") + section.segmentName + + "/" + section.sectionName + + " is supposed to contain 0x0000 " + "terminated UTF16 strings, but the " + "last string in the section is not zero " + "terminated."); + } + return error_code::success(); +} + +// A __DATA/__cfstring section contain NS/CFString objects. Atom boundaries +// are determined because each object is known to be 4 pointers in size. +static error_code processCFStringSection(MachOFile &file,const Section §ion, + bool is64, bool copyRefs) { + const uint32_t cfsObjSize = (is64 ? 32 : 16); + if ((section.content.size() % cfsObjSize) != 0) { + return make_dynamic_error_code(Twine("Section __DATA/__cfstring has a size " + "(" + Twine(section.content.size()) + + ") that is not a multiple of " + + Twine(cfsObjSize))); + } + unsigned offset = 0; + for (size_t i = 0, e = section.content.size(); i != e; i += cfsObjSize) { + ArrayRef<uint8_t> byteContent = section.content.slice(offset, cfsObjSize); + file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit, + DefinedAtom::typeCFString, + DefinedAtom::mergeByContent, byteContent, copyRefs); + offset += cfsObjSize; + } + return error_code::success(); +} + static error_code processSection(MachOFile &file, const Section §ion, bool is64, bool copyRefs) { unsigned offset = 0; const unsigned pointerSize = (is64 ? 8 : 4); switch (section.type) { case llvm::MachO::S_REGULAR: - if (section.segmentName.equals("__TEXT") && + if (section.segmentName.equals("__TEXT") && section.sectionName.equals("__ustring")) { - if ((section.content.size() % 4) != 0) - return make_dynamic_error_code(Twine("Section ") + section.segmentName - + "/" + section.sectionName - + " has a size that is not even"); - for (size_t i = 0, e = section.content.size(); i != e; i +=2) { - if ((section.content[i] == 0) && (section.content[i+1] == 0)) { - unsigned size = i - offset + 2; - ArrayRef<uint8_t> utf16Content = section.content.slice(offset, size); - file.addDefinedAtom(StringRef(), DefinedAtom::scopeLinkageUnit, - DefinedAtom::typeUTF16String, - DefinedAtom::mergeByContent, utf16Content, - copyRefs); - offset = i + 2; - } - } - if (offset != section.content.size()) { - return make_dynamic_error_code(Twine("Section ") + section.segmentName - + "/" + section.sectionName - + " is supposed to contain 0x0000 " - "terminated UTF16 strings, but the " - "last string in the section is not zero " - "terminated."); - } + return processUTF16Section(file, section, is64, copyRefs); + } + else if (section.segmentName.equals("__DATA") && + section.sectionName.equals("__cfstring")) { + return processCFStringSection(file, section, is64, copyRefs); } break; case llvm::MachO::S_COALESCED: |

