diff options
| author | Nick Kledzik <kledzik@apple.com> | 2014-05-29 23:07:20 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2014-05-29 23:07:20 +0000 |
| commit | b367c25f289e1897c967a5166ee442234f5dab3e (patch) | |
| tree | d6a4997fc3d26c554f545c26c32df017933f7d86 /lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | |
| parent | 3012a1b4cd6a7d4cc295f9c70ebc643ece5deac0 (diff) | |
| download | bcm5719-llvm-b367c25f289e1897c967a5166ee442234f5dab3e.tar.gz bcm5719-llvm-b367c25f289e1897c967a5166ee442234f5dab3e.zip | |
[mach-o] Add support for parsing __eh_frame section. Generalize support for whether symbols in a section are ignored or illegal
llvm-svn: 209858
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | 125 |
1 files changed, 104 insertions, 21 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index c06289a1061..569f32f09de 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -21,6 +21,7 @@ /// +-------+ #include "MachONormalizedFile.h" +#include "MachONormalizedFileBinaryUtils.h" #include "File.h" #include "Atoms.h" @@ -35,8 +36,14 @@ namespace lld { namespace mach_o { namespace normalized { +enum SymbolsInSection { + symbolsOk, + symbolsIgnored, + symbolsIllegal +}; + static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile, - const Symbol &symbol) { + const Symbol &symbol) { uint64_t symbolAddr = symbol.value; uint8_t symbolSectionIndex = symbol.sect; const Section §ion = normalizedFile.sections[symbolSectionIndex - 1]; @@ -80,19 +87,38 @@ static DefinedAtom::ContentType atomTypeFromSection(const Section §ion) { return DefinedAtom::typeCode; } -static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, - const Symbol &sym, bool copyRefs) { - // Mach-O symbol table does have size in it, so need to scan ahead - // to find symbol with next highest address. +static error_code +processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, + const Symbol &sym, bool copyRefs, + const SmallVector<SymbolsInSection, 32> symbolsInSect) { + if (sym.sect > normalizedFile.sections.size()) { + int sectionIndex = sym.sect; + return make_dynamic_error_code(Twine("Symbol '") + sym.name + + "' has n_sect (" + + Twine(sectionIndex) + + ") which is too large"); + } const Section §ion = normalizedFile.sections[sym.sect - 1]; + switch (symbolsInSect[sym.sect-1]) { + case symbolsOk: + break; + case symbolsIgnored: + return error_code::success(); + break; + case symbolsIllegal: + return make_dynamic_error_code(Twine("Symbol '") + sym.name + + "' is not legal in section " + + section.segmentName + "/" + + section.sectionName); + break; + } + uint64_t offset = sym.value - section.address; + // Mach-O symbol table does have size in it, so need to scan ahead + // to find symbol with next highest address. uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value; 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; @@ -101,6 +127,7 @@ static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file, file.addDefinedAtom(sym.name, atomScope(sym.scope), atomTypeFromSection(section), m, atomContent, copyRefs); } + return error_code::success(); } @@ -168,22 +195,63 @@ static error_code processCFStringSection(MachOFile &file,const Section §ion, return error_code::success(); } + +// A __TEXT/__eh_frame section contains dwarf unwind CFIs (either CIE or FDE). +// Atom boundaries are determined by looking at the length content header +// in each CFI. +static error_code processCFISection(MachOFile &file, const Section §ion, + bool is64, bool swap, bool copyRefs) { + const unsigned char* buffer = section.content.data(); + for (size_t offset = 0, end = section.content.size(); offset < end; ) { + size_t remaining = end - offset; + if (remaining < 16) { + return make_dynamic_error_code(Twine("Section __TEXT/__eh_frame is " + "malformed. Not enough room left for " + "a CFI starting at offset (" + + Twine(offset) + + ")")); + } + const uint32_t *cfi = reinterpret_cast<const uint32_t *>(&buffer[offset]); + uint32_t len = read32(swap, *cfi) + 4; + if (offset+len > end) { + return make_dynamic_error_code(Twine("Section __TEXT/__eh_frame is " + "malformed. Size of CFI starting at " + "at offset (" + + Twine(offset) + + ") is past end of section.")); + } + ArrayRef<uint8_t> bytes = section.content.slice(offset, len); + file.addDefinedAtom(StringRef(), DefinedAtom::scopeTranslationUnit, + DefinedAtom::typeCFI, DefinedAtom::mergeNo, + bytes, copyRefs); + offset += len; + } + return error_code::success(); +} + static error_code processSection(MachOFile &file, const Section §ion, - bool is64, bool copyRefs) { + bool is64, bool swap, bool copyRefs, + SymbolsInSection &symbolsInSect) { unsigned offset = 0; const unsigned pointerSize = (is64 ? 8 : 4); switch (section.type) { case llvm::MachO::S_REGULAR: if (section.segmentName.equals("__TEXT") && section.sectionName.equals("__ustring")) { + symbolsInSect = symbolsIgnored; return processUTF16Section(file, section, is64, copyRefs); - } - else if (section.segmentName.equals("__DATA") && + } else if (section.segmentName.equals("__DATA") && section.sectionName.equals("__cfstring")) { + symbolsInSect = symbolsIllegal; return processCFStringSection(file, section, is64, copyRefs); } break; case llvm::MachO::S_COALESCED: + if (section.segmentName.equals("__TEXT") && + section.sectionName.equals("__eh_frame")) { + symbolsInSect = symbolsIgnored; + return processCFISection(file, section, is64, swap, copyRefs); + } case llvm::MachO::S_ZEROFILL: // These sections are broken into atoms based on symbols. break; @@ -204,6 +272,7 @@ static error_code processSection(MachOFile &file, const Section §ion, bytes, copyRefs); offset += pointerSize; } + symbolsInSect = symbolsIllegal; break; case S_MOD_TERM_FUNC_POINTERS: if ((section.content.size() % pointerSize) != 0) { @@ -222,6 +291,7 @@ static error_code processSection(MachOFile &file, const Section §ion, bytes, copyRefs); offset += pointerSize; } + symbolsInSect = symbolsIllegal; break; case S_NON_LAZY_SYMBOL_POINTERS: if ((section.content.size() % pointerSize) != 0) { @@ -240,6 +310,7 @@ static error_code processSection(MachOFile &file, const Section §ion, bytes, copyRefs); offset += pointerSize; } + symbolsInSect = symbolsIllegal; break; case llvm::MachO::S_CSTRING_LITERALS: for (size_t i = 0, e = section.content.size(); i != e; ++i) { @@ -259,6 +330,7 @@ static error_code processSection(MachOFile &file, const Section §ion, "last string in the section is not zero " "terminated."); } + symbolsInSect = symbolsIgnored; break; case llvm::MachO::S_4BYTE_LITERALS: if ((section.content.size() % 4) != 0) @@ -274,6 +346,7 @@ static error_code processSection(MachOFile &file, const Section §ion, DefinedAtom::mergeByContent, byteContent, copyRefs); offset += 4; } + symbolsInSect = symbolsIllegal; break; case llvm::MachO::S_8BYTE_LITERALS: if ((section.content.size() % 8) != 0) @@ -289,6 +362,7 @@ static error_code processSection(MachOFile &file, const Section §ion, DefinedAtom::mergeByContent, byteContent, copyRefs); offset += 8; } + symbolsInSect = symbolsIllegal; break; case llvm::MachO::S_16BYTE_LITERALS: if ((section.content.size() % 16) != 0) @@ -304,6 +378,7 @@ static error_code processSection(MachOFile &file, const Section §ion, DefinedAtom::mergeByContent, byteContent, copyRefs); offset += 16; } + symbolsInSect = symbolsIllegal; break; default: llvm_unreachable("mach-o section type not supported yet"); @@ -317,24 +392,32 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, bool copyRefs) { std::unique_ptr<MachOFile> file(new MachOFile(path)); + // Create atoms from sections that don't have symbols. + bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch); + bool swap = !MachOLinkingContext::isHostEndian(normalizedFile.arch); + SmallVector<SymbolsInSection, 32> symbolsInSect; + for (auto § : normalizedFile.sections) { + symbolsInSect.push_back(symbolsOk); + if (error_code ec = processSection(*file, sect, is64, swap, copyRefs, + symbolsInSect.back())) + return ec; + } // Create atoms from global symbols. for (const Symbol &sym : normalizedFile.globalSymbols) { - processSymbol(normalizedFile, *file, sym, copyRefs); + if (error_code ec = processSymbol(normalizedFile, *file, sym, copyRefs, + symbolsInSect)) + return ec; } // Create atoms from local symbols. for (const Symbol &sym : normalizedFile.localSymbols) { - processSymbol(normalizedFile, *file, sym, copyRefs); + if (error_code ec = processSymbol(normalizedFile, *file, sym, copyRefs, + symbolsInSect)) + return ec; } - // Create atoms from undefinded symbols. + // Create atoms from undefined symbols. for (auto &sym : normalizedFile.undefinedSymbols) { processUndefindeSymbol(*file, sym, copyRefs); } - // Create atoms from sections that don't have symbols. - bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch); - for (auto § : normalizedFile.sections) { - if (error_code ec = processSection(*file, sect, is64, copyRefs)) - return ec; - } return std::unique_ptr<File>(std::move(file)); } |

