15e508b9bSDjordje Todorovic //===-- SectionSizes.cpp - Debug section sizes ----------------------------===//
25e508b9bSDjordje Todorovic //
35e508b9bSDjordje Todorovic // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45e508b9bSDjordje Todorovic // See https://llvm.org/LICENSE.txt for license information.
55e508b9bSDjordje Todorovic // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65e508b9bSDjordje Todorovic //
75e508b9bSDjordje Todorovic //===----------------------------------------------------------------------===//
85e508b9bSDjordje Todorovic
9b1849231SFangrui Song #include "llvm-dwarfdump.h"
105e508b9bSDjordje Todorovic
115e508b9bSDjordje Todorovic #define DEBUG_TYPE "dwarfdump"
125e508b9bSDjordje Todorovic
135e508b9bSDjordje Todorovic using namespace llvm;
14b1849231SFangrui Song using namespace llvm::dwarfdump;
15b1849231SFangrui Song using namespace llvm::object;
165e508b9bSDjordje Todorovic
getNameColumnWidth(const SectionSizes & Sizes,const StringRef SectionNameTitle)175e508b9bSDjordje Todorovic static size_t getNameColumnWidth(const SectionSizes &Sizes,
185e508b9bSDjordje Todorovic const StringRef SectionNameTitle) {
195e508b9bSDjordje Todorovic // The minimum column width should be the size of "SECTION".
205e508b9bSDjordje Todorovic size_t Width = SectionNameTitle.size();
21599711dcSFangrui Song for (const auto &It : Sizes.DebugSectionSizes)
22599711dcSFangrui Song Width = std::max(Width, It.first.size());
235e508b9bSDjordje Todorovic return Width;
245e508b9bSDjordje Todorovic }
255e508b9bSDjordje Todorovic
getSizeColumnWidth(const SectionSizes & Sizes,const StringRef SectionSizeTitle)265e508b9bSDjordje Todorovic static size_t getSizeColumnWidth(const SectionSizes &Sizes,
275e508b9bSDjordje Todorovic const StringRef SectionSizeTitle) {
285e508b9bSDjordje Todorovic // The minimum column width should be the size of the column title.
295e508b9bSDjordje Todorovic size_t Width = SectionSizeTitle.size();
30599711dcSFangrui Song for (const auto &It : Sizes.DebugSectionSizes) {
31599711dcSFangrui Song size_t NumWidth = std::to_string(It.second).size();
325e508b9bSDjordje Todorovic Width = std::max(Width, NumWidth);
335e508b9bSDjordje Todorovic }
345e508b9bSDjordje Todorovic return Width;
355e508b9bSDjordje Todorovic }
365e508b9bSDjordje Todorovic
prettyPrintSectionSizes(const ObjectFile & Obj,const SectionSizes & Sizes,raw_ostream & OS)375e508b9bSDjordje Todorovic static void prettyPrintSectionSizes(const ObjectFile &Obj,
385e508b9bSDjordje Todorovic const SectionSizes &Sizes,
395e508b9bSDjordje Todorovic raw_ostream &OS) {
405e508b9bSDjordje Todorovic const StringRef SectionNameTitle = "SECTION";
415e508b9bSDjordje Todorovic const StringRef SectionSizeTitle = "SIZE (b)";
425e508b9bSDjordje Todorovic
435e508b9bSDjordje Todorovic size_t NameColWidth = getNameColumnWidth(Sizes, SectionNameTitle);
445e508b9bSDjordje Todorovic size_t SizeColWidth = getSizeColumnWidth(Sizes, SectionSizeTitle);
455e508b9bSDjordje Todorovic
465e508b9bSDjordje Todorovic OS << "----------------------------------------------------" << '\n';
475e508b9bSDjordje Todorovic OS << SectionNameTitle;
485e508b9bSDjordje Todorovic size_t SectionNameTitleWidth = SectionNameTitle.size();
495e508b9bSDjordje Todorovic for (unsigned i = 0; i < (NameColWidth - SectionNameTitleWidth) + 2; i++)
505e508b9bSDjordje Todorovic OS << " ";
515e508b9bSDjordje Todorovic OS << SectionSizeTitle << '\n';
525e508b9bSDjordje Todorovic for (unsigned i = 0; i < NameColWidth; i++)
535e508b9bSDjordje Todorovic OS << "-";
545e508b9bSDjordje Todorovic OS << " ";
555e508b9bSDjordje Todorovic
565e508b9bSDjordje Todorovic for (unsigned i = 0; i < SizeColWidth; i++)
575e508b9bSDjordje Todorovic OS << "-";
585e508b9bSDjordje Todorovic OS << '\n';
595e508b9bSDjordje Todorovic
60599711dcSFangrui Song for (const auto &It : Sizes.DebugSectionSizes) {
61599711dcSFangrui Song OS << left_justify(It.first, NameColWidth) << " ";
625e508b9bSDjordje Todorovic
63599711dcSFangrui Song std::string NumBytes = std::to_string(It.second);
645e508b9bSDjordje Todorovic OS << right_justify(NumBytes, SizeColWidth) << " ("
65599711dcSFangrui Song << format("%0.2f",
66599711dcSFangrui Song It.second / static_cast<double>(Sizes.TotalObjectSize) * 100)
675e508b9bSDjordje Todorovic << "%)\n";
685e508b9bSDjordje Todorovic }
695e508b9bSDjordje Todorovic
705e508b9bSDjordje Todorovic OS << '\n';
715e508b9bSDjordje Todorovic OS << " Total Size: " << Sizes.TotalDebugSectionsSize << " ("
725e508b9bSDjordje Todorovic << format("%0.2f", Sizes.TotalDebugSectionsSize /
735e508b9bSDjordje Todorovic static_cast<double>(Sizes.TotalObjectSize) * 100)
745e508b9bSDjordje Todorovic << "%)\n";
755e508b9bSDjordje Todorovic OS << " Total File Size: " << Sizes.TotalObjectSize << '\n';
765e508b9bSDjordje Todorovic OS << "----------------------------------------------------" << '\n';
775e508b9bSDjordje Todorovic }
785e508b9bSDjordje Todorovic
calculateSectionSizes(const ObjectFile & Obj,SectionSizes & Sizes,const Twine & Filename)79b1849231SFangrui Song void dwarfdump::calculateSectionSizes(const ObjectFile &Obj,
80b1849231SFangrui Song SectionSizes &Sizes,
815e508b9bSDjordje Todorovic const Twine &Filename) {
825e508b9bSDjordje Todorovic // Get total size.
835e508b9bSDjordje Todorovic Sizes.TotalObjectSize = Obj.getData().size();
845e508b9bSDjordje Todorovic
855e508b9bSDjordje Todorovic for (const SectionRef &Section : Obj.sections()) {
865e508b9bSDjordje Todorovic StringRef SectionName;
875e508b9bSDjordje Todorovic if (Expected<StringRef> NameOrErr = Section.getName())
885e508b9bSDjordje Todorovic SectionName = *NameOrErr;
895e508b9bSDjordje Todorovic else
905e508b9bSDjordje Todorovic WithColor::defaultWarningHandler(
915e508b9bSDjordje Todorovic createFileError(Filename, NameOrErr.takeError()));
925e508b9bSDjordje Todorovic
935e508b9bSDjordje Todorovic LLVM_DEBUG(dbgs() << SectionName.str() << ": " << Section.getSize()
945e508b9bSDjordje Todorovic << '\n');
955e508b9bSDjordje Todorovic
96*bf809cd1SEsme-Yi if (!Section.isDebugSection())
975e508b9bSDjordje Todorovic continue;
985e508b9bSDjordje Todorovic
995e508b9bSDjordje Todorovic Sizes.TotalDebugSectionsSize += Section.getSize();
100599711dcSFangrui Song Sizes.DebugSectionSizes[std::string(SectionName)] += Section.getSize();
1015e508b9bSDjordje Todorovic }
1025e508b9bSDjordje Todorovic }
1035e508b9bSDjordje Todorovic
collectObjectSectionSizes(ObjectFile & Obj,DWARFContext &,const Twine & Filename,raw_ostream & OS)104b1849231SFangrui Song bool dwarfdump::collectObjectSectionSizes(ObjectFile &Obj,
105b1849231SFangrui Song DWARFContext & /*DICtx*/,
106b1849231SFangrui Song const Twine &Filename,
107b1849231SFangrui Song raw_ostream &OS) {
1085e508b9bSDjordje Todorovic SectionSizes Sizes;
1095e508b9bSDjordje Todorovic
1105e508b9bSDjordje Todorovic // Get the section sizes.
1115e508b9bSDjordje Todorovic calculateSectionSizes(Obj, Sizes, Filename);
1125e508b9bSDjordje Todorovic
1135e508b9bSDjordje Todorovic OS << "----------------------------------------------------\n";
1145e508b9bSDjordje Todorovic OS << "file: " << Filename.str() << '\n';
1155e508b9bSDjordje Todorovic
1165e508b9bSDjordje Todorovic prettyPrintSectionSizes(Obj, Sizes, OS);
1175e508b9bSDjordje Todorovic
1185e508b9bSDjordje Todorovic // TODO: If the input file is an archive, print the cumulative summary of all
1195e508b9bSDjordje Todorovic // files from the archive.
1205e508b9bSDjordje Todorovic
1215e508b9bSDjordje Todorovic return true;
1225e508b9bSDjordje Todorovic }
123