summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-05-29 20:44:21 +0000
committerNick Kledzik <kledzik@apple.com>2014-05-29 20:44:21 +0000
commit9ede702bc4ef97df625c0e69be225f1fd5a6a55c (patch)
tree82c81a981efae2eeda64d2917ecbb07fc145d615 /lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
parentc6b506a0ae3bf1e6902f2fe83b62ed945a8c30e0 (diff)
downloadbcm5719-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.cpp89
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 &section = 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 &section,
+ 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 &section,
+ 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 &section,
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:
OpenPOWER on IntegriCloud