llvm-project/llvm/tools/llvm-dwarfdump/SectionSizes.cpp

125 lines
4.3 KiB
C++

//===-- 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 &DebugSec : Sizes.DebugSectionSizes) {
StringRef SectionName = DebugSec.getKey();
Width = std::max(Width, SectionName.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 &DebugSec : Sizes.DebugSectionSizes) {
size_t NumWidth = std::to_string(DebugSec.getValue()).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 &DebugSec : Sizes.DebugSectionSizes) {
OS << left_justify(DebugSec.getKey(), NameColWidth) << " ";
auto NumBytes = std::to_string(DebugSec.getValue());
OS << right_justify(NumBytes, SizeColWidth) << " ("
<< format("%0.2f", DebugSec.getValue() /
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(SectionName))
continue;
Sizes.TotalDebugSectionsSize += Section.getSize();
Sizes.DebugSectionSizes[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;
}