1097a140dSpatrick //===-- SectionSizes.cpp - Debug section sizes ----------------------------===//
2097a140dSpatrick //
3097a140dSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4097a140dSpatrick // See https://llvm.org/LICENSE.txt for license information.
5097a140dSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6097a140dSpatrick //
7097a140dSpatrick //===----------------------------------------------------------------------===//
8097a140dSpatrick
9097a140dSpatrick #include "llvm-dwarfdump.h"
10097a140dSpatrick
11097a140dSpatrick #define DEBUG_TYPE "dwarfdump"
12097a140dSpatrick
13097a140dSpatrick using namespace llvm;
14097a140dSpatrick using namespace llvm::dwarfdump;
15097a140dSpatrick using namespace llvm::object;
16097a140dSpatrick
getNameColumnWidth(const SectionSizes & Sizes,const StringRef SectionNameTitle)17097a140dSpatrick static size_t getNameColumnWidth(const SectionSizes &Sizes,
18097a140dSpatrick const StringRef SectionNameTitle) {
19097a140dSpatrick // The minimum column width should be the size of "SECTION".
20097a140dSpatrick size_t Width = SectionNameTitle.size();
21*73471bf0Spatrick for (const auto &It : Sizes.DebugSectionSizes)
22*73471bf0Spatrick Width = std::max(Width, It.first.size());
23097a140dSpatrick return Width;
24097a140dSpatrick }
25097a140dSpatrick
getSizeColumnWidth(const SectionSizes & Sizes,const StringRef SectionSizeTitle)26097a140dSpatrick static size_t getSizeColumnWidth(const SectionSizes &Sizes,
27097a140dSpatrick const StringRef SectionSizeTitle) {
28097a140dSpatrick // The minimum column width should be the size of the column title.
29097a140dSpatrick size_t Width = SectionSizeTitle.size();
30*73471bf0Spatrick for (const auto &It : Sizes.DebugSectionSizes) {
31*73471bf0Spatrick size_t NumWidth = std::to_string(It.second).size();
32097a140dSpatrick Width = std::max(Width, NumWidth);
33097a140dSpatrick }
34097a140dSpatrick return Width;
35097a140dSpatrick }
36097a140dSpatrick
prettyPrintSectionSizes(const ObjectFile & Obj,const SectionSizes & Sizes,raw_ostream & OS)37097a140dSpatrick static void prettyPrintSectionSizes(const ObjectFile &Obj,
38097a140dSpatrick const SectionSizes &Sizes,
39097a140dSpatrick raw_ostream &OS) {
40097a140dSpatrick const StringRef SectionNameTitle = "SECTION";
41097a140dSpatrick const StringRef SectionSizeTitle = "SIZE (b)";
42097a140dSpatrick
43097a140dSpatrick size_t NameColWidth = getNameColumnWidth(Sizes, SectionNameTitle);
44097a140dSpatrick size_t SizeColWidth = getSizeColumnWidth(Sizes, SectionSizeTitle);
45097a140dSpatrick
46097a140dSpatrick OS << "----------------------------------------------------" << '\n';
47097a140dSpatrick OS << SectionNameTitle;
48097a140dSpatrick size_t SectionNameTitleWidth = SectionNameTitle.size();
49097a140dSpatrick for (unsigned i = 0; i < (NameColWidth - SectionNameTitleWidth) + 2; i++)
50097a140dSpatrick OS << " ";
51097a140dSpatrick OS << SectionSizeTitle << '\n';
52097a140dSpatrick for (unsigned i = 0; i < NameColWidth; i++)
53097a140dSpatrick OS << "-";
54097a140dSpatrick OS << " ";
55097a140dSpatrick
56097a140dSpatrick for (unsigned i = 0; i < SizeColWidth; i++)
57097a140dSpatrick OS << "-";
58097a140dSpatrick OS << '\n';
59097a140dSpatrick
60*73471bf0Spatrick for (const auto &It : Sizes.DebugSectionSizes) {
61*73471bf0Spatrick OS << left_justify(It.first, NameColWidth) << " ";
62097a140dSpatrick
63*73471bf0Spatrick std::string NumBytes = std::to_string(It.second);
64097a140dSpatrick OS << right_justify(NumBytes, SizeColWidth) << " ("
65*73471bf0Spatrick << format("%0.2f",
66*73471bf0Spatrick It.second / static_cast<double>(Sizes.TotalObjectSize) * 100)
67097a140dSpatrick << "%)\n";
68097a140dSpatrick }
69097a140dSpatrick
70097a140dSpatrick OS << '\n';
71097a140dSpatrick OS << " Total Size: " << Sizes.TotalDebugSectionsSize << " ("
72097a140dSpatrick << format("%0.2f", Sizes.TotalDebugSectionsSize /
73097a140dSpatrick static_cast<double>(Sizes.TotalObjectSize) * 100)
74097a140dSpatrick << "%)\n";
75097a140dSpatrick OS << " Total File Size: " << Sizes.TotalObjectSize << '\n';
76097a140dSpatrick OS << "----------------------------------------------------" << '\n';
77097a140dSpatrick }
78097a140dSpatrick
calculateSectionSizes(const ObjectFile & Obj,SectionSizes & Sizes,const Twine & Filename)79097a140dSpatrick void dwarfdump::calculateSectionSizes(const ObjectFile &Obj,
80097a140dSpatrick SectionSizes &Sizes,
81097a140dSpatrick const Twine &Filename) {
82097a140dSpatrick // Get total size.
83097a140dSpatrick Sizes.TotalObjectSize = Obj.getData().size();
84097a140dSpatrick
85097a140dSpatrick for (const SectionRef &Section : Obj.sections()) {
86097a140dSpatrick StringRef SectionName;
87097a140dSpatrick if (Expected<StringRef> NameOrErr = Section.getName())
88097a140dSpatrick SectionName = *NameOrErr;
89097a140dSpatrick else
90097a140dSpatrick WithColor::defaultWarningHandler(
91097a140dSpatrick createFileError(Filename, NameOrErr.takeError()));
92097a140dSpatrick
93097a140dSpatrick LLVM_DEBUG(dbgs() << SectionName.str() << ": " << Section.getSize()
94097a140dSpatrick << '\n');
95097a140dSpatrick
96*73471bf0Spatrick if (!Section.isDebugSection())
97097a140dSpatrick continue;
98097a140dSpatrick
99097a140dSpatrick Sizes.TotalDebugSectionsSize += Section.getSize();
100*73471bf0Spatrick Sizes.DebugSectionSizes[std::string(SectionName)] += Section.getSize();
101097a140dSpatrick }
102097a140dSpatrick }
103097a140dSpatrick
collectObjectSectionSizes(ObjectFile & Obj,DWARFContext &,const Twine & Filename,raw_ostream & OS)104097a140dSpatrick bool dwarfdump::collectObjectSectionSizes(ObjectFile &Obj,
105097a140dSpatrick DWARFContext & /*DICtx*/,
106097a140dSpatrick const Twine &Filename,
107097a140dSpatrick raw_ostream &OS) {
108097a140dSpatrick SectionSizes Sizes;
109097a140dSpatrick
110097a140dSpatrick // Get the section sizes.
111097a140dSpatrick calculateSectionSizes(Obj, Sizes, Filename);
112097a140dSpatrick
113097a140dSpatrick OS << "----------------------------------------------------\n";
114097a140dSpatrick OS << "file: " << Filename.str() << '\n';
115097a140dSpatrick
116097a140dSpatrick prettyPrintSectionSizes(Obj, Sizes, OS);
117097a140dSpatrick
118097a140dSpatrick // TODO: If the input file is an archive, print the cumulative summary of all
119097a140dSpatrick // files from the archive.
120097a140dSpatrick
121097a140dSpatrick return true;
122097a140dSpatrick }
123