diff options
Diffstat (limited to 'lld/MachO/SyntheticSections.cpp')
-rw-r--r-- | lld/MachO/SyntheticSections.cpp | 104 |
1 files changed, 100 insertions, 4 deletions
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index 5d603d6f90d3..feaa4b5d3e22 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -20,7 +20,9 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/Support/EndianStream.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::support; @@ -574,17 +576,100 @@ SymtabSection::SymtabSection(StringTableSection &stringTableSection) stringTableSection(stringTableSection) {} uint64_t SymtabSection::getRawSize() const { - return symbols.size() * sizeof(structs::nlist_64); + return getNumSymbols() * sizeof(structs::nlist_64); +} + +void SymtabSection::emitBeginSourceStab(DWARFUnit *compileUnit) { + StabsEntry stab(MachO::N_SO); + SmallString<261> dir(compileUnit->getCompilationDir()); + StringRef sep = sys::path::get_separator(); + // We don't use `path::append` here because we want an empty `dir` to result + // in an absolute path. `append` would give us a relative path for that case. + if (!dir.endswith(sep)) + dir += sep; + stab.strx = stringTableSection.addString( + saver.save(dir + compileUnit->getUnitDIE().getShortName())); + stabs.emplace_back(std::move(stab)); +} + +void SymtabSection::emitEndSourceStab() { + StabsEntry stab(MachO::N_SO); + stab.sect = 1; + stabs.emplace_back(std::move(stab)); +} + +void SymtabSection::emitObjectFileStab(ObjFile *file) { + StabsEntry stab(MachO::N_OSO); + stab.sect = target->cpuSubtype; + SmallString<261> path(file->getName()); + std::error_code ec = sys::fs::make_absolute(path); + if (ec) + fatal("failed to get absolute path for " + file->getName()); + + stab.strx = stringTableSection.addString(saver.save(path.str())); + stab.desc = 1; + stabs.emplace_back(std::move(stab)); +} + +void SymtabSection::emitFunStabs(Defined *defined) { + { + StabsEntry stab(MachO::N_FUN); + stab.sect = 1; + stab.strx = stringTableSection.addString(defined->getName()); + stab.value = defined->getVA(); + stabs.emplace_back(std::move(stab)); + } + + { + StabsEntry stab(MachO::N_FUN); + // FIXME this should be the size of the symbol. Using the section size in + // lieu is only correct if .subsections_via_symbols is set. + stab.value = defined->isec->getSize(); + stabs.emplace_back(std::move(stab)); + } } void SymtabSection::finalizeContents() { - // TODO support other symbol types + InputFile *lastFile = nullptr; for (Symbol *sym : symtab->getSymbols()) { + // TODO support other symbol types if (isa<Defined>(sym) || sym->isInGot() || sym->isInStubs()) { sym->symtabIndex = symbols.size(); symbols.push_back({sym, stringTableSection.addString(sym->getName())}); } + + // Emit STABS symbols so that dsymutil and/or the debugger can map address + // regions in the final binary to the source and object files from which + // they originated. + if (auto *defined = dyn_cast<Defined>(sym)) { + if (defined->isAbsolute()) + continue; + + InputSection *isec = defined->isec; + // XXX is it right to assume that all symbols in __text are function + // symbols? + if (isec->name == "__text") { + ObjFile *file = dyn_cast<ObjFile>(isec->file); + assert(file); + if (!file->compileUnit) + continue; + + if (lastFile == nullptr || lastFile != file) { + if (lastFile != nullptr) + emitEndSourceStab(); + lastFile = file; + + emitBeginSourceStab(file->compileUnit); + emitObjectFileStab(file); + } + emitFunStabs(defined); + } + // TODO emit stabs for non-function symbols too + } } + + if (!stabs.empty()) + emitEndSourceStab(); } void SymtabSection::writeTo(uint8_t *buf) const { @@ -602,12 +687,23 @@ void SymtabSection::writeTo(uint8_t *buf) const { nList->n_type = MachO::N_EXT | MachO::N_SECT; nList->n_sect = defined->isec->parent->index; // For the N_SECT symbol type, n_value is the address of the symbol - nList->n_value = defined->value + defined->isec->getVA(); + nList->n_value = defined->getVA(); } nList->n_desc |= defined->isWeakDef() ? MachO::N_WEAK_DEF : 0; } ++nList; } + + // Emit the stabs entries after the "real" symbols. We cannot emit them + // before as that would render Symbol::symtabIndex inaccurate. + for (const StabsEntry &entry : stabs) { + nList->n_strx = entry.strx; + nList->n_type = entry.type; + nList->n_sect = entry.sect; + nList->n_desc = entry.desc; + nList->n_value = entry.value; + ++nList; + } } IndirectSymtabSection::IndirectSymtabSection() @@ -656,7 +752,7 @@ StringTableSection::StringTableSection() uint32_t StringTableSection::addString(StringRef str) { uint32_t strx = size; - strings.push_back(str); + strings.push_back(str); // TODO: consider deduplicating strings size += str.size() + 1; // account for null terminator return strx; } |