
When loading split debug files for PE/COFF executables (produced with `objcopy --only-keep-debug`), the tables or directories in such files may point to data inside sections that may have been stripped. COFFObjectFile shall detect and gracefully handle this, to allow the object file be loaded without considering these tables or directories. This is required for LLDB to load these files for use as debug symbols. COFFObjectFile shall also check these pointers more carefully to account for cases in which the section contains less raw data than the size given by VirtualSize, to prevent going out of bounds. This commit also changes COFFDump in llvm-objdump to reuse the pointers that are already range-checked in COFFObjectFile. This fixes a crash when trying to dump the TLS directory from a stripped file. Fixes https://github.com/mstorsjo/llvm-mingw/issues/284 Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D126898
97 lines
3.4 KiB
C++
97 lines
3.4 KiB
C++
//===- Error.cpp - system_error extensions for Object -----------*- 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This defines a new error_category for the Object library.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Object/Error.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/ManagedStatic.h"
|
|
|
|
using namespace llvm;
|
|
using namespace object;
|
|
|
|
namespace {
|
|
// FIXME: This class is only here to support the transition to llvm::Error. It
|
|
// will be removed once this transition is complete. Clients should prefer to
|
|
// deal with the Error value directly, rather than converting to error_code.
|
|
class _object_error_category : public std::error_category {
|
|
public:
|
|
const char* name() const noexcept override;
|
|
std::string message(int ev) const override;
|
|
};
|
|
}
|
|
|
|
const char *_object_error_category::name() const noexcept {
|
|
return "llvm.object";
|
|
}
|
|
|
|
std::string _object_error_category::message(int EV) const {
|
|
object_error E = static_cast<object_error>(EV);
|
|
switch (E) {
|
|
case object_error::arch_not_found:
|
|
return "No object file for requested architecture";
|
|
case object_error::invalid_file_type:
|
|
return "The file was not recognized as a valid object file";
|
|
case object_error::parse_failed:
|
|
return "Invalid data was encountered while parsing the file";
|
|
case object_error::unexpected_eof:
|
|
return "The end of the file was unexpectedly encountered";
|
|
case object_error::string_table_non_null_end:
|
|
return "String table must end with a null terminator";
|
|
case object_error::invalid_section_index:
|
|
return "Invalid section index";
|
|
case object_error::bitcode_section_not_found:
|
|
return "Bitcode section not found in object file";
|
|
case object_error::invalid_symbol_index:
|
|
return "Invalid symbol index";
|
|
case object_error::section_stripped:
|
|
return "Section has been stripped from the object file";
|
|
}
|
|
llvm_unreachable("An enumerator of object_error does not have a message "
|
|
"defined.");
|
|
}
|
|
|
|
void BinaryError::anchor() {}
|
|
char BinaryError::ID = 0;
|
|
char GenericBinaryError::ID = 0;
|
|
|
|
GenericBinaryError::GenericBinaryError(const Twine &Msg) : Msg(Msg.str()) {}
|
|
|
|
GenericBinaryError::GenericBinaryError(const Twine &Msg,
|
|
object_error ECOverride)
|
|
: Msg(Msg.str()) {
|
|
setErrorCode(make_error_code(ECOverride));
|
|
}
|
|
|
|
void GenericBinaryError::log(raw_ostream &OS) const {
|
|
OS << Msg;
|
|
}
|
|
|
|
static ManagedStatic<_object_error_category> error_category;
|
|
|
|
const std::error_category &object::object_category() {
|
|
return *error_category;
|
|
}
|
|
|
|
llvm::Error llvm::object::isNotObjectErrorInvalidFileType(llvm::Error Err) {
|
|
return handleErrors(std::move(Err), [](std::unique_ptr<ECError> M) -> Error {
|
|
// Try to handle 'M'. If successful, return a success value from
|
|
// the handler.
|
|
if (M->convertToErrorCode() == object_error::invalid_file_type)
|
|
return Error::success();
|
|
|
|
// We failed to handle 'M' - return it from the handler.
|
|
// This value will be passed back from catchErrors and
|
|
// wind up in Err2, where it will be returned from this function.
|
|
return Error(std::move(M));
|
|
});
|
|
}
|