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