summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-07-24 23:06:56 +0000
committerNick Kledzik <kledzik@apple.com>2014-07-24 23:06:56 +0000
commit21921375cc23d4958560b3280c2684c9c52baa62 (patch)
tree0eb10637cd0350312f9a2d326b95f7b735c87e73 /lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
parent8ec1474f7f5f1673f6ea0bc47bdbded62fefde0e (diff)
downloadbcm5719-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.cpp68
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 &section,
@@ -441,17 +452,10 @@ std::error_code convertRelocs(const Section &section,
"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();
OpenPOWER on IntegriCloud