xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===-- SectionSizes.cpp - Debug section sizes ----------------------------===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #include "llvm-dwarfdump.h"
10*5ffd83dbSDimitry Andric 
11*5ffd83dbSDimitry Andric #define DEBUG_TYPE "dwarfdump"
12*5ffd83dbSDimitry Andric 
13*5ffd83dbSDimitry Andric using namespace llvm;
14*5ffd83dbSDimitry Andric using namespace llvm::dwarfdump;
15*5ffd83dbSDimitry Andric using namespace llvm::object;
16*5ffd83dbSDimitry Andric 
17*5ffd83dbSDimitry Andric static size_t getNameColumnWidth(const SectionSizes &Sizes,
18*5ffd83dbSDimitry Andric                                  const StringRef SectionNameTitle) {
19*5ffd83dbSDimitry Andric   // The minimum column width should be the size of "SECTION".
20*5ffd83dbSDimitry Andric   size_t Width = SectionNameTitle.size();
21*5ffd83dbSDimitry Andric   for (const auto &DebugSec : Sizes.DebugSectionSizes) {
22*5ffd83dbSDimitry Andric     StringRef SectionName = DebugSec.getKey();
23*5ffd83dbSDimitry Andric     Width = std::max(Width, SectionName.size());
24*5ffd83dbSDimitry Andric   }
25*5ffd83dbSDimitry Andric   return Width;
26*5ffd83dbSDimitry Andric }
27*5ffd83dbSDimitry Andric 
28*5ffd83dbSDimitry Andric static size_t getSizeColumnWidth(const SectionSizes &Sizes,
29*5ffd83dbSDimitry Andric                                  const StringRef SectionSizeTitle) {
30*5ffd83dbSDimitry Andric   // The minimum column width should be the size of the column title.
31*5ffd83dbSDimitry Andric   size_t Width = SectionSizeTitle.size();
32*5ffd83dbSDimitry Andric   for (const auto &DebugSec : Sizes.DebugSectionSizes) {
33*5ffd83dbSDimitry Andric     size_t NumWidth = std::to_string(DebugSec.getValue()).size();
34*5ffd83dbSDimitry Andric     Width = std::max(Width, NumWidth);
35*5ffd83dbSDimitry Andric   }
36*5ffd83dbSDimitry Andric   return Width;
37*5ffd83dbSDimitry Andric }
38*5ffd83dbSDimitry Andric 
39*5ffd83dbSDimitry Andric static void prettyPrintSectionSizes(const ObjectFile &Obj,
40*5ffd83dbSDimitry Andric                                     const SectionSizes &Sizes,
41*5ffd83dbSDimitry Andric                                     raw_ostream &OS) {
42*5ffd83dbSDimitry Andric   const StringRef SectionNameTitle = "SECTION";
43*5ffd83dbSDimitry Andric   const StringRef SectionSizeTitle = "SIZE (b)";
44*5ffd83dbSDimitry Andric 
45*5ffd83dbSDimitry Andric   size_t NameColWidth = getNameColumnWidth(Sizes, SectionNameTitle);
46*5ffd83dbSDimitry Andric   size_t SizeColWidth = getSizeColumnWidth(Sizes, SectionSizeTitle);
47*5ffd83dbSDimitry Andric 
48*5ffd83dbSDimitry Andric   OS << "----------------------------------------------------" << '\n';
49*5ffd83dbSDimitry Andric   OS << SectionNameTitle;
50*5ffd83dbSDimitry Andric   size_t SectionNameTitleWidth = SectionNameTitle.size();
51*5ffd83dbSDimitry Andric   for (unsigned i = 0; i < (NameColWidth - SectionNameTitleWidth) + 2; i++)
52*5ffd83dbSDimitry Andric     OS << " ";
53*5ffd83dbSDimitry Andric   OS << SectionSizeTitle << '\n';
54*5ffd83dbSDimitry Andric   for (unsigned i = 0; i < NameColWidth; i++)
55*5ffd83dbSDimitry Andric     OS << "-";
56*5ffd83dbSDimitry Andric   OS << "  ";
57*5ffd83dbSDimitry Andric 
58*5ffd83dbSDimitry Andric   for (unsigned i = 0; i < SizeColWidth; i++)
59*5ffd83dbSDimitry Andric     OS << "-";
60*5ffd83dbSDimitry Andric   OS << '\n';
61*5ffd83dbSDimitry Andric 
62*5ffd83dbSDimitry Andric   for (const auto &DebugSec : Sizes.DebugSectionSizes) {
63*5ffd83dbSDimitry Andric     OS << left_justify(DebugSec.getKey(), NameColWidth) << "  ";
64*5ffd83dbSDimitry Andric 
65*5ffd83dbSDimitry Andric     auto NumBytes = std::to_string(DebugSec.getValue());
66*5ffd83dbSDimitry Andric     OS << right_justify(NumBytes, SizeColWidth) << " ("
67*5ffd83dbSDimitry Andric        << format("%0.2f", DebugSec.getValue() /
68*5ffd83dbSDimitry Andric                               static_cast<double>(Sizes.TotalObjectSize) * 100)
69*5ffd83dbSDimitry Andric        << "%)\n";
70*5ffd83dbSDimitry Andric   }
71*5ffd83dbSDimitry Andric 
72*5ffd83dbSDimitry Andric   OS << '\n';
73*5ffd83dbSDimitry Andric   OS << " Total Size: " << Sizes.TotalDebugSectionsSize << "  ("
74*5ffd83dbSDimitry Andric      << format("%0.2f", Sizes.TotalDebugSectionsSize /
75*5ffd83dbSDimitry Andric                             static_cast<double>(Sizes.TotalObjectSize) * 100)
76*5ffd83dbSDimitry Andric      << "%)\n";
77*5ffd83dbSDimitry Andric   OS << " Total File Size: " << Sizes.TotalObjectSize << '\n';
78*5ffd83dbSDimitry Andric   OS << "----------------------------------------------------" << '\n';
79*5ffd83dbSDimitry Andric }
80*5ffd83dbSDimitry Andric 
81*5ffd83dbSDimitry Andric void dwarfdump::calculateSectionSizes(const ObjectFile &Obj,
82*5ffd83dbSDimitry Andric                                       SectionSizes &Sizes,
83*5ffd83dbSDimitry Andric                                       const Twine &Filename) {
84*5ffd83dbSDimitry Andric   // Get total size.
85*5ffd83dbSDimitry Andric   Sizes.TotalObjectSize = Obj.getData().size();
86*5ffd83dbSDimitry Andric 
87*5ffd83dbSDimitry Andric   for (const SectionRef &Section : Obj.sections()) {
88*5ffd83dbSDimitry Andric     StringRef SectionName;
89*5ffd83dbSDimitry Andric     if (Expected<StringRef> NameOrErr = Section.getName())
90*5ffd83dbSDimitry Andric       SectionName = *NameOrErr;
91*5ffd83dbSDimitry Andric     else
92*5ffd83dbSDimitry Andric       WithColor::defaultWarningHandler(
93*5ffd83dbSDimitry Andric           createFileError(Filename, NameOrErr.takeError()));
94*5ffd83dbSDimitry Andric 
95*5ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << SectionName.str() << ": " << Section.getSize()
96*5ffd83dbSDimitry Andric                       << '\n');
97*5ffd83dbSDimitry Andric 
98*5ffd83dbSDimitry Andric     if (!Section.isDebugSection(SectionName))
99*5ffd83dbSDimitry Andric       continue;
100*5ffd83dbSDimitry Andric 
101*5ffd83dbSDimitry Andric     Sizes.TotalDebugSectionsSize += Section.getSize();
102*5ffd83dbSDimitry Andric     Sizes.DebugSectionSizes[SectionName] += Section.getSize();
103*5ffd83dbSDimitry Andric   }
104*5ffd83dbSDimitry Andric }
105*5ffd83dbSDimitry Andric 
106*5ffd83dbSDimitry Andric bool dwarfdump::collectObjectSectionSizes(ObjectFile &Obj,
107*5ffd83dbSDimitry Andric                                           DWARFContext & /*DICtx*/,
108*5ffd83dbSDimitry Andric                                           const Twine &Filename,
109*5ffd83dbSDimitry Andric                                           raw_ostream &OS) {
110*5ffd83dbSDimitry Andric   SectionSizes Sizes;
111*5ffd83dbSDimitry Andric 
112*5ffd83dbSDimitry Andric   // Get the section sizes.
113*5ffd83dbSDimitry Andric   calculateSectionSizes(Obj, Sizes, Filename);
114*5ffd83dbSDimitry Andric 
115*5ffd83dbSDimitry Andric   OS << "----------------------------------------------------\n";
116*5ffd83dbSDimitry Andric   OS << "file: " << Filename.str() << '\n';
117*5ffd83dbSDimitry Andric 
118*5ffd83dbSDimitry Andric   prettyPrintSectionSizes(Obj, Sizes, OS);
119*5ffd83dbSDimitry Andric 
120*5ffd83dbSDimitry Andric   // TODO: If the input file is an archive, print the cumulative summary of all
121*5ffd83dbSDimitry Andric   // files from the archive.
122*5ffd83dbSDimitry Andric 
123*5ffd83dbSDimitry Andric   return true;
124*5ffd83dbSDimitry Andric }
125