|  | //===-- SectionSizes.cpp - Debug section sizes ----------------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm-dwarfdump.h" | 
|  |  | 
|  | #define DEBUG_TYPE "dwarfdump" | 
|  |  | 
|  | using namespace llvm; | 
|  | using namespace llvm::dwarfdump; | 
|  | using namespace llvm::object; | 
|  |  | 
|  | static size_t getNameColumnWidth(const SectionSizes &Sizes, | 
|  | const StringRef SectionNameTitle) { | 
|  | // The minimum column width should be the size of "SECTION". | 
|  | size_t Width = SectionNameTitle.size(); | 
|  | for (const auto &It : Sizes.DebugSectionSizes) | 
|  | Width = std::max(Width, It.first.size()); | 
|  | return Width; | 
|  | } | 
|  |  | 
|  | static size_t getSizeColumnWidth(const SectionSizes &Sizes, | 
|  | const StringRef SectionSizeTitle) { | 
|  | // The minimum column width should be the size of the column title. | 
|  | size_t Width = SectionSizeTitle.size(); | 
|  | for (const auto &It : Sizes.DebugSectionSizes) { | 
|  | size_t NumWidth = std::to_string(It.second).size(); | 
|  | Width = std::max(Width, NumWidth); | 
|  | } | 
|  | return Width; | 
|  | } | 
|  |  | 
|  | static void prettyPrintSectionSizes(const ObjectFile &Obj, | 
|  | const SectionSizes &Sizes, | 
|  | raw_ostream &OS) { | 
|  | const StringRef SectionNameTitle = "SECTION"; | 
|  | const StringRef SectionSizeTitle = "SIZE (b)"; | 
|  |  | 
|  | size_t NameColWidth = getNameColumnWidth(Sizes, SectionNameTitle); | 
|  | size_t SizeColWidth = getSizeColumnWidth(Sizes, SectionSizeTitle); | 
|  |  | 
|  | OS << "----------------------------------------------------" << '\n'; | 
|  | OS << SectionNameTitle; | 
|  | size_t SectionNameTitleWidth = SectionNameTitle.size(); | 
|  | for (unsigned i = 0; i < (NameColWidth - SectionNameTitleWidth) + 2; i++) | 
|  | OS << " "; | 
|  | OS << SectionSizeTitle << '\n'; | 
|  | for (unsigned i = 0; i < NameColWidth; i++) | 
|  | OS << "-"; | 
|  | OS << "  "; | 
|  |  | 
|  | for (unsigned i = 0; i < SizeColWidth; i++) | 
|  | OS << "-"; | 
|  | OS << '\n'; | 
|  |  | 
|  | for (const auto &It : Sizes.DebugSectionSizes) { | 
|  | OS << left_justify(It.first, NameColWidth) << "  "; | 
|  |  | 
|  | std::string NumBytes = std::to_string(It.second); | 
|  | OS << right_justify(NumBytes, SizeColWidth) << " (" | 
|  | << format("%0.2f", | 
|  | It.second / static_cast<double>(Sizes.TotalObjectSize) * 100) | 
|  | << "%)\n"; | 
|  | } | 
|  |  | 
|  | OS << '\n'; | 
|  | OS << " Total Size: " << Sizes.TotalDebugSectionsSize << "  (" | 
|  | << format("%0.2f", Sizes.TotalDebugSectionsSize / | 
|  | static_cast<double>(Sizes.TotalObjectSize) * 100) | 
|  | << "%)\n"; | 
|  | OS << " Total File Size: " << Sizes.TotalObjectSize << '\n'; | 
|  | OS << "----------------------------------------------------" << '\n'; | 
|  | } | 
|  |  | 
|  | void dwarfdump::calculateSectionSizes(const ObjectFile &Obj, | 
|  | SectionSizes &Sizes, | 
|  | const Twine &Filename) { | 
|  | // Get total size. | 
|  | Sizes.TotalObjectSize = Obj.getData().size(); | 
|  |  | 
|  | for (const SectionRef &Section : Obj.sections()) { | 
|  | StringRef SectionName; | 
|  | if (Expected<StringRef> NameOrErr = Section.getName()) | 
|  | SectionName = *NameOrErr; | 
|  | else | 
|  | WithColor::defaultWarningHandler( | 
|  | createFileError(Filename, NameOrErr.takeError())); | 
|  |  | 
|  | LLVM_DEBUG(dbgs() << SectionName.str() << ": " << Section.getSize() | 
|  | << '\n'); | 
|  |  | 
|  | if (!Section.isDebugSection()) | 
|  | continue; | 
|  |  | 
|  | Sizes.TotalDebugSectionsSize += Section.getSize(); | 
|  | Sizes.DebugSectionSizes[std::string(SectionName)] += Section.getSize(); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool dwarfdump::collectObjectSectionSizes(ObjectFile &Obj, | 
|  | DWARFContext & /*DICtx*/, | 
|  | const Twine &Filename, | 
|  | raw_ostream &OS) { | 
|  | SectionSizes Sizes; | 
|  |  | 
|  | // Get the section sizes. | 
|  | calculateSectionSizes(Obj, Sizes, Filename); | 
|  |  | 
|  | OS << "----------------------------------------------------\n"; | 
|  | OS << "file: " << Filename.str() << '\n'; | 
|  |  | 
|  | prettyPrintSectionSizes(Obj, Sizes, OS); | 
|  |  | 
|  | // TODO: If the input file is an archive, print the cumulative summary of all | 
|  | // files from the archive. | 
|  |  | 
|  | return true; | 
|  | } |