diff options
| author | Nick Kledzik <kledzik@apple.com> | 2014-07-24 23:06:56 +0000 |
|---|---|---|
| committer | Nick Kledzik <kledzik@apple.com> | 2014-07-24 23:06:56 +0000 |
| commit | 21921375cc23d4958560b3280c2684c9c52baa62 (patch) | |
| tree | 0eb10637cd0350312f9a2d326b95f7b735c87e73 /lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | |
| parent | 8ec1474f7f5f1673f6ea0bc47bdbded62fefde0e (diff) | |
| download | bcm5719-llvm-21921375cc23d4958560b3280c2684c9c52baa62.tar.gz bcm5719-llvm-21921375cc23d4958560b3280c2684c9c52baa62.zip | |
[mach-o] Add support for LC_DATA_IN_CODE
Sometimes compilers emit data into code sections (e.g. constant pools or
jump tables). These runs of data can throw off disassemblers. The solution
in mach-o is that ranges of data-in-code are encoded into a table pointed to
by the LC_DATA_IN_CODE load command.
The way the data-in-code information is encoded into lld's Atom model is that
that start and end of each data run is marked with a Reference whose offset
is the start/end of the data run. For arm, the switch back to code also marks
whether it is thumb or arm code.
llvm-svn: 213901
Diffstat (limited to 'lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 437c8d1281a..900c9eb9680 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -426,6 +426,17 @@ std::error_code processSection(DefinedAtom::ContentType atomType, return std::error_code(); } +const Section* findSectionCoveringAddress(const NormalizedFile &normalizedFile, + uint64_t address) { + for (const Section &s : normalizedFile.sections) { + uint64_t sAddr = s.address; + if ((sAddr <= address) && (address < sAddr+s.content.size())) { + return &s; + } + } + return nullptr; +} + // Walks all relocations for a section in a normalized .o file and // creates corresponding lld::Reference objects. std::error_code convertRelocs(const Section §ion, @@ -441,17 +452,10 @@ std::error_code convertRelocs(const Section §ion, "index (") + Twine(sectIndex) + ")"); const Section *sect = nullptr; if (sectIndex == 0) { - for (const Section &s : normalizedFile.sections) { - uint64_t sAddr = s.address; - if ((sAddr <= addr) && (addr < sAddr+s.content.size())) { - sect = &s; - break; - } - } - if (!sect) { + sect = findSectionCoveringAddress(normalizedFile, addr); + if (!sect) return make_dynamic_error_code(Twine("address (" + Twine(addr) - + ") is not in any section")); - } + + ") is not in any section")); } else { sect = &normalizedFile.sections[sectIndex-1]; } @@ -612,6 +616,50 @@ normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path, handler->addAdditionalReferences(*atom); }); + // Process mach-o data-in-code regions array. That information is encoded in + // atoms as References at each transition point. + unsigned nextIndex = 0; + for (const DataInCode &entry : normalizedFile.dataInCode) { + ++nextIndex; + const Section* s = findSectionCoveringAddress(normalizedFile, entry.offset); + if (!s) { + return make_dynamic_error_code(Twine("LC_DATA_IN_CODE address (" + + Twine(entry.offset) + + ") is not in any section")); + } + uint64_t offsetInSect = entry.offset - s->address; + uint32_t offsetInAtom; + MachODefinedAtom *atom = file->findAtomCoveringAddress(*s, offsetInSect, + &offsetInAtom); + if (offsetInAtom + entry.length > atom->size()) { + return make_dynamic_error_code(Twine("LC_DATA_IN_CODE entry (offset=" + + Twine(entry.offset) + + ", length=" + + Twine(entry.length) + + ") crosses atom boundary.")); + } + // Add reference that marks start of data-in-code. + atom->addReference(offsetInAtom, + handler->dataInCodeTransitionStart(*atom), atom, + entry.kind, handler->kindArch()); + + // Peek at next entry, if it starts where this one ends, skip ending ref. + if (nextIndex < normalizedFile.dataInCode.size()) { + const DataInCode &nextEntry = normalizedFile.dataInCode[nextIndex]; + if (nextEntry.offset == (entry.offset + entry.length)) + continue; + } + + // If data goes to end of function, skip ending ref. + if ((offsetInAtom + entry.length) == atom->size()) + continue; + + // Add reference that marks end of data-in-code. + atom->addReference(offsetInAtom+entry.length, + handler->dataInCodeTransitionEnd(*atom), atom, 0, + handler->kindArch()); + } + // Sort references in each atom to their canonical order. for (const DefinedAtom* defAtom : file->defined()) { reinterpret_cast<const SimpleDefinedAtom*>(defAtom)->sortReferences(); |

