std::string resolveOrDie(const URI &U, llvm::StringRef HintPath = "") { auto Path = URI::resolve(U, HintPath); if (!Path) llvm_unreachable(toString(Path.takeError()).c_str()); return *Path; }
// Returns true on error. static bool format(StringRef FileName) { if (!OutputXML && Inplace && FileName == "-") { errs() << "error: cannot use -i when reading from stdin.\n"; return false; } // On Windows, overwriting a file with an open file mapping doesn't work, // so read the whole file into memory when formatting in-place. ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr = !OutputXML && Inplace ? MemoryBuffer::getFileAsStream(FileName) : MemoryBuffer::getFileOrSTDIN(FileName); if (std::error_code EC = CodeOrErr.getError()) { errs() << EC.message() << "\n"; return true; } std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get()); if (Code->getBufferSize() == 0) return false; // Empty files are formatted correctly. std::vector<tooling::Range> Ranges; if (fillRanges(Code.get(), Ranges)) return true; StringRef AssumedFileName = (FileName == "-") ? AssumeFileName : FileName; llvm::Expected<FormatStyle> FormatStyle = getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer()); if (!FormatStyle) { llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n"; return true; } if (SortIncludes.getNumOccurrences() != 0) FormatStyle->SortIncludes = SortIncludes; unsigned CursorPosition = Cursor; Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges, AssumedFileName, &CursorPosition); auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces); if (!ChangedCode) { llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n"; return true; } // Get new affected ranges after sorting `#includes`. Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); FormattingAttemptStatus Status; Replacements FormatChanges = reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status); Replaces = Replaces.merge(FormatChanges); if (OutputXML) { outs() << "<?xml version='1.0'?>\n<replacements " "xml:space='preserve' incomplete_format='" << (Status.FormatComplete ? "false" : "true") << "'"; if (!Status.FormatComplete) outs() << " line='" << Status.Line << "'"; outs() << ">\n"; if (Cursor.getNumOccurrences() != 0) outs() << "<cursor>" << FormatChanges.getShiftedCodePosition(CursorPosition) << "</cursor>\n"; outputReplacementsXML(Replaces); outs() << "</replacements>\n"; } else { IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem( new vfs::InMemoryFileSystem); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), new DiagnosticOptions); SourceManager Sources(Diagnostics, Files); FileID ID = createInMemoryFile(AssumedFileName, Code.get(), Sources, Files, InMemoryFileSystem.get()); Rewriter Rewrite(Sources, LangOptions()); tooling::applyAllReplacements(Replaces, Rewrite); if (Inplace) { if (Rewrite.overwriteChangedFiles()) return true; } else { if (Cursor.getNumOccurrences() != 0) { outs() << "{ \"Cursor\": " << FormatChanges.getShiftedCodePosition(CursorPosition) << ", \"IncompleteFormat\": " << (Status.FormatComplete ? "false" : "true"); if (!Status.FormatComplete) outs() << ", \"Line\": " << Status.Line; outs() << " }\n"; } Rewrite.getEditBuffer(ID).write(outs()); } } return false; }
llvm::Expected<std::string> URI::includeSpelling(const URI &Uri) { auto S = findSchemeByName(Uri.Scheme); if (!S) return S.takeError(); return S->get()->getIncludeSpelling(Uri); }
URI URI::createFile(llvm::StringRef AbsolutePath) { auto U = create(AbsolutePath, "file"); if (!U) llvm_unreachable(llvm::toString(U.takeError()).c_str()); return std::move(*U); }
llvm::Expected<IndexFileIn> readRIFF(llvm::StringRef Data) { auto RIFF = riff::readFile(Data); if (!RIFF) return RIFF.takeError(); if (RIFF->Type != riff::fourCC("CdIx")) return makeError("wrong RIFF type"); llvm::StringMap<llvm::StringRef> Chunks; for (const auto &Chunk : RIFF->Chunks) Chunks.try_emplace(llvm::StringRef(Chunk.ID.data(), Chunk.ID.size()), Chunk.Data); for (llvm::StringRef RequiredChunk : {"meta", "stri"}) if (!Chunks.count(RequiredChunk)) return makeError("missing required chunk " + RequiredChunk); Reader Meta(Chunks.lookup("meta")); if (Meta.consume32() != Version) return makeError("wrong version"); auto Strings = readStringTable(Chunks.lookup("stri")); if (!Strings) return Strings.takeError(); IndexFileIn Result; if (Chunks.count("srcs")) { Reader SrcsReader(Chunks.lookup("srcs")); Result.Sources.emplace(); while (!SrcsReader.eof()) { auto IGN = readIncludeGraphNode(SrcsReader, Strings->Strings); auto Entry = Result.Sources->try_emplace(IGN.URI).first; Entry->getValue() = std::move(IGN); // We change all the strings inside the structure to point at the keys in // the map, since it is the only copy of the string that's going to live. Entry->getValue().URI = Entry->getKey(); for (auto &Include : Entry->getValue().DirectIncludes) Include = Result.Sources->try_emplace(Include).first->getKey(); } if (SrcsReader.err()) return makeError("malformed or truncated include uri"); } if (Chunks.count("symb")) { Reader SymbolReader(Chunks.lookup("symb")); SymbolSlab::Builder Symbols; while (!SymbolReader.eof()) Symbols.insert(readSymbol(SymbolReader, Strings->Strings)); if (SymbolReader.err()) return makeError("malformed or truncated symbol"); Result.Symbols = std::move(Symbols).build(); } if (Chunks.count("refs")) { Reader RefsReader(Chunks.lookup("refs")); RefSlab::Builder Refs; while (!RefsReader.eof()) { auto RefsBundle = readRefs(RefsReader, Strings->Strings); for (const auto &Ref : RefsBundle.second) // FIXME: bulk insert? Refs.insert(RefsBundle.first, Ref); } if (RefsReader.err()) return makeError("malformed or truncated refs"); Result.Refs = std::move(Refs).build(); } return std::move(Result); }
static Error getRelocationValueString(const ELFObjectFile<ELFT> *Obj, const RelocationRef &RelRef, SmallVectorImpl<char> &Result) { const ELFFile<ELFT> &EF = *Obj->getELFFile(); DataRefImpl Rel = RelRef.getRawDataRefImpl(); auto SecOrErr = EF.getSection(Rel.d.a); if (!SecOrErr) return SecOrErr.takeError(); int64_t Addend = 0; // If there is no Symbol associated with the relocation, we set the undef // boolean value to 'true'. This will prevent us from calling functions that // requires the relocation to be associated with a symbol. // // In SHT_REL case we would need to read the addend from section data. // GNU objdump does not do that and we just follow for simplicity atm. bool Undef = false; if ((*SecOrErr)->sh_type == ELF::SHT_RELA) { const typename ELFT::Rela *ERela = Obj->getRela(Rel); Addend = ERela->r_addend; Undef = ERela->getSymbol(false) == 0; } else if ((*SecOrErr)->sh_type != ELF::SHT_REL) { return make_error<BinaryError>(); } // Default scheme is to print Target, as well as "+ <addend>" for nonzero // addend. Should be acceptable for all normal purposes. std::string FmtBuf; raw_string_ostream Fmt(FmtBuf); if (!Undef) { symbol_iterator SI = RelRef.getSymbol(); const typename ELFT::Sym *Sym = Obj->getSymbol(SI->getRawDataRefImpl()); if (Sym->getType() == ELF::STT_SECTION) { Expected<section_iterator> SymSI = SI->getSection(); if (!SymSI) return SymSI.takeError(); const typename ELFT::Shdr *SymSec = Obj->getSection((*SymSI)->getRawDataRefImpl()); auto SecName = EF.getSectionName(SymSec); if (!SecName) return SecName.takeError(); Fmt << *SecName; } else { Expected<StringRef> SymName = SI->getName(); if (!SymName) return SymName.takeError(); if (Demangle) Fmt << demangle(*SymName); else Fmt << *SymName; } } else { Fmt << "*ABS*"; } if (Addend != 0) Fmt << (Addend < 0 ? "" : "+") << Addend; Fmt.flush(); Result.append(FmtBuf.begin(), FmtBuf.end()); return Error::success(); }
template <class ELFT> void printProgramHeaders(const ELFFile<ELFT> *o) { outs() << "Program Header:\n"; auto ProgramHeaderOrError = o->program_headers(); if (!ProgramHeaderOrError) report_fatal_error(toString(ProgramHeaderOrError.takeError())); for (const typename ELFT::Phdr &Phdr : *ProgramHeaderOrError) { switch (Phdr.p_type) { case ELF::PT_DYNAMIC: outs() << " DYNAMIC "; break; case ELF::PT_GNU_EH_FRAME: outs() << "EH_FRAME "; break; case ELF::PT_GNU_RELRO: outs() << " RELRO "; break; case ELF::PT_GNU_STACK: outs() << " STACK "; break; case ELF::PT_INTERP: outs() << " INTERP "; break; case ELF::PT_LOAD: outs() << " LOAD "; break; case ELF::PT_NOTE: outs() << " NOTE "; break; case ELF::PT_OPENBSD_BOOTDATA: outs() << " OPENBSD_BOOTDATA "; break; case ELF::PT_OPENBSD_RANDOMIZE: outs() << " OPENBSD_RANDOMIZE "; break; case ELF::PT_OPENBSD_WXNEEDED: outs() << " OPENBSD_WXNEEDED "; break; case ELF::PT_PHDR: outs() << " PHDR "; break; case ELF::PT_TLS: outs() << " TLS "; break; default: outs() << " UNKNOWN "; } const char *Fmt = ELFT::Is64Bits ? "0x%016" PRIx64 " " : "0x%08" PRIx64 " "; outs() << "off " << format(Fmt, (uint64_t)Phdr.p_offset) << "vaddr " << format(Fmt, (uint64_t)Phdr.p_vaddr) << "paddr " << format(Fmt, (uint64_t)Phdr.p_paddr) << format("align 2**%u\n", countTrailingZeros<uint64_t>(Phdr.p_align)) << " filesz " << format(Fmt, (uint64_t)Phdr.p_filesz) << "memsz " << format(Fmt, (uint64_t)Phdr.p_memsz) << "flags " << ((Phdr.p_flags & ELF::PF_R) ? "r" : "-") << ((Phdr.p_flags & ELF::PF_W) ? "w" : "-") << ((Phdr.p_flags & ELF::PF_X) ? "x" : "-") << "\n"; } outs() << "\n"; }