1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00
Stephen Tozer b86c4a2cbe [llvm-readobj] Improve error message for --string-dump
Fixes bug 40630: https://bugs.llvm.org/show_bug.cgi?id=40630

This patch changes the error message when the section specified by
--string-dump cannot be found by including the name of the section in
the error message and changing the prefix text to not imply that the
file itself was invalid. As part of this change some uses of
std::error_code have been replaced with the llvm Error class to better
encapsulate the error info (rather than passing File strings around),
and the WithColor class replaces string literal error prefixes.

Differential Revision: https://reviews.llvm.org/D59946

llvm-svn: 357772
2019-04-05 16:15:50 +00:00

150 lines
4.8 KiB
C++

//===-- ObjDumper.cpp - Base dumper class -----------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements ObjDumper.
///
//===----------------------------------------------------------------------===//
#include "ObjDumper.h"
#include "Error.h"
#include "llvm-readobj.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
ObjDumper::ObjDumper(ScopedPrinter &Writer) : W(Writer) {}
ObjDumper::~ObjDumper() {
}
static void printAsPrintable(raw_ostream &W, const uint8_t *Start, size_t Len) {
for (size_t i = 0; i < Len; i++)
W << (isPrint(Start[i]) ? static_cast<char>(Start[i]) : '.');
}
static Expected<object::SectionRef>
getSecNameOrIndexAsSecRef(const object::ObjectFile *Obj, StringRef SecName) {
char *StrPtr;
long SectionIndex = strtol(SecName.data(), &StrPtr, 10);
long SecIndex;
if (Obj->isELF())
SecIndex = 0;
else
SecIndex = 1;
for (object::SectionRef SecRef : Obj->sections()) {
if (*StrPtr) {
StringRef SectionName;
if (std::error_code E = SecRef.getName(SectionName))
return errorCodeToError(E);
if (SectionName == SecName)
return SecRef;
} else if (SecIndex == SectionIndex)
return SecRef;
SecIndex++;
}
return make_error<StringError>(
formatv("could not find section '{0}'", SecName),
object::object_error::parse_failed);
}
void ObjDumper::printSectionAsString(const object::ObjectFile *Obj,
StringRef SecName) {
Expected<object::SectionRef> SectionRefOrError =
getSecNameOrIndexAsSecRef(Obj, SecName);
if (!SectionRefOrError)
error(std::move(SectionRefOrError));
object::SectionRef Section = *SectionRefOrError;
StringRef SectionName;
if (std::error_code E = Section.getName(SectionName))
error(E);
W.startLine() << "String dump of section '" << SectionName << "':\n";
StringRef SectionContent;
Section.getContents(SectionContent);
const uint8_t *SecContent = SectionContent.bytes_begin();
const uint8_t *CurrentWord = SecContent;
const uint8_t *SecEnd = SectionContent.bytes_end();
while (CurrentWord <= SecEnd) {
size_t WordSize = strnlen(reinterpret_cast<const char *>(CurrentWord),
SecEnd - CurrentWord);
if (!WordSize) {
CurrentWord++;
continue;
}
W.startLine() << format("[%6tx] ", CurrentWord - SecContent);
printAsPrintable(W.startLine(), CurrentWord, WordSize);
W.startLine() << '\n';
CurrentWord += WordSize + 1;
}
}
void ObjDumper::printSectionAsHex(const object::ObjectFile *Obj,
StringRef SecName) {
Expected<object::SectionRef> SectionRefOrError =
getSecNameOrIndexAsSecRef(Obj, SecName);
if (!SectionRefOrError)
error(std::move(SectionRefOrError));
object::SectionRef Section = *SectionRefOrError;
StringRef SectionName;
if (std::error_code E = Section.getName(SectionName))
error(E);
W.startLine() << "Hex dump of section '" << SectionName << "':\n";
StringRef SectionContent;
Section.getContents(SectionContent);
const uint8_t *SecContent = SectionContent.bytes_begin();
const uint8_t *SecEnd = SecContent + SectionContent.size();
for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) {
const uint8_t *TmpSecPtr = SecPtr;
uint8_t i;
uint8_t k;
W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent),
10);
W.startLine() << ' ';
for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr));
W.startLine() << format_hex_no_prefix(Val, 2);
}
W.startLine() << ' ';
}
// We need to print the correct amount of spaces to match the format.
// We are adding the (4 - i) last rows that are 8 characters each.
// Then, the (4 - i) spaces that are in between the rows.
// Least, if we cut in a middle of a row, we add the remaining characters,
// which is (8 - (k * 2)).
if (i < 4)
W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)),
' ');
TmpSecPtr = SecPtr;
for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i)
W.startLine() << (isPrint(TmpSecPtr[i]) ? static_cast<char>(TmpSecPtr[i])
: '.');
W.startLine() << '\n';
}
}
} // namespace llvm