CodeView: extract the OMF Directory Header

The DebugDirectory contains a pointer to the CodeView info structure which is a
derivative of the OMF debug directory.  The structure has evolved a bit over
time, and PDB 2.0 used a slightly different definition from PDB 7.0.  Both of
these are specific to CodeView and not COFF.  Reflect this by moving the
structure definitions into the DebugInfo/CodeView headers.  Define a generic
DebugInfo union type that can be used to pass around a reference to the
DebugInfo irrespective of the versioning.  NFC.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278075 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Saleem Abdulrasool 2016-08-09 00:25:12 +00:00
parent f7c3c99642
commit b79146f48d
5 changed files with 79 additions and 28 deletions

View File

@ -0,0 +1,55 @@
//===- CVDebugRecord.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_CVDEBUGRECORD_H
#include "llvm/Support/Endian.h"
namespace llvm {
namespace OMF {
struct Signature {
enum ID : uint32_t {
PDB70 = 0x53445352, // RSDS
PDB20 = 0x3031424e, // NB10
CV50 = 0x3131424e, // NB11
CV41 = 0x3930424e, // NB09
};
support::ulittle32_t CVSignature;
support::ulittle32_t Offset;
};
}
namespace codeview {
struct PDB70DebugInfo {
support::ulittle32_t CVSignature;
uint8_t Signature[16];
support::ulittle32_t Age;
// char PDBFileName[];
};
struct PDB20DebugInfo {
support::ulittle32_t CVSignature;
support::ulittle32_t Offset;
support::ulittle32_t Signature;
support::ulittle32_t Age;
// char PDBFileName[];
};
union DebugInfo {
struct OMF::Signature Signature;
struct PDB20DebugInfo PDB20;
struct PDB70DebugInfo PDB70;
};
}
}
#endif

View File

@ -15,6 +15,7 @@
#define LLVM_OBJECT_COFF_H
#include "llvm/ADT/PointerUnion.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Endian.h"
@ -172,15 +173,6 @@ struct debug_directory {
support::ulittle32_t PointerToRawData;
};
/// Information that is resent in debug_directory::AddressOfRawData if Type is
/// IMAGE_DEBUG_TYPE_CODEVIEW.
struct debug_pdb_info {
support::ulittle32_t Signature;
uint8_t Guid[16];
support::ulittle32_t Age;
// PDBFileName: The null-terminated PDB file name follows.
};
template <typename IntTy>
struct import_lookup_table_entry {
IntTy Data;
@ -868,14 +860,14 @@ public:
/// Get PDB information out of a codeview debug directory entry.
std::error_code getDebugPDBInfo(const debug_directory *DebugDir,
const debug_pdb_info *&Info,
const codeview::DebugInfo *&Info,
StringRef &PDBFileName) const;
/// Get PDB information from an executable. If the information is not present,
/// Info will be set to nullptr and PDBFileName will be empty. An error is
/// returned only on corrupt object files. Convenience accessor that can be
/// used if the debug directory is not already handy.
std::error_code getDebugPDBInfo(const debug_pdb_info *&Info,
std::error_code getDebugPDBInfo(const codeview::DebugInfo *&Info,
StringRef &PDBFileName) const;
bool isRelocatableObject() const override;

View File

@ -391,10 +391,10 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
// If this is a COFF object containing PDB info, use a PDBContext to
// symbolize. Otherwise, use DWARF.
if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
const debug_pdb_info *PDBInfo;
const codeview::DebugInfo *DebugInfo;
StringRef PDBFileName;
auto EC = CoffObject->getDebugPDBInfo(PDBInfo, PDBFileName);
if (!EC && PDBInfo != nullptr) {
auto EC = CoffObject->getDebugPDBInfo(DebugInfo, PDBFileName);
if (!EC && DebugInfo != nullptr) {
using namespace pdb;
std::unique_ptr<IPDBSession> Session;
if (auto Err = loadDataForEXE(PDB_ReaderType::DIA,

View File

@ -487,17 +487,18 @@ std::error_code COFFObjectFile::getHintName(uint32_t Rva, uint16_t &Hint,
return std::error_code();
}
std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
const debug_pdb_info *&PDBInfo,
StringRef &PDBFileName) const {
std::error_code
COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
const codeview::DebugInfo *&PDBInfo,
StringRef &PDBFileName) const {
ArrayRef<uint8_t> InfoBytes;
if (std::error_code EC = getRvaAndSizeAsBytes(
DebugDir->AddressOfRawData, DebugDir->SizeOfData, InfoBytes))
return EC;
if (InfoBytes.size() < sizeof(debug_pdb_info) + 1)
if (InfoBytes.size() < sizeof(*PDBInfo) + 1)
return object_error::parse_failed;
PDBInfo = reinterpret_cast<const debug_pdb_info *>(InfoBytes.data());
InfoBytes = InfoBytes.drop_front(sizeof(debug_pdb_info));
PDBInfo = reinterpret_cast<const codeview::DebugInfo *>(InfoBytes.data());
InfoBytes = InfoBytes.drop_front(sizeof(*PDBInfo));
PDBFileName = StringRef(reinterpret_cast<const char *>(InfoBytes.data()),
InfoBytes.size());
// Truncate the name at the first null byte. Ignore any padding.
@ -505,8 +506,9 @@ std::error_code COFFObjectFile::getDebugPDBInfo(const debug_directory *DebugDir,
return std::error_code();
}
std::error_code COFFObjectFile::getDebugPDBInfo(const debug_pdb_info *&PDBInfo,
StringRef &PDBFileName) const {
std::error_code
COFFObjectFile::getDebugPDBInfo(const codeview::DebugInfo *&PDBInfo,
StringRef &PDBFileName) const {
for (const debug_directory &D : debug_directories())
if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
return getDebugPDBInfo(&D, PDBInfo, PDBFileName);

View File

@ -670,14 +670,16 @@ void COFFDumper::printCOFFDebugDirectory() {
W.printHex("AddressOfRawData", D.AddressOfRawData);
W.printHex("PointerToRawData", D.PointerToRawData);
if (D.Type == COFF::IMAGE_DEBUG_TYPE_CODEVIEW) {
const debug_pdb_info *PDBInfo;
const codeview::DebugInfo *DebugInfo;
StringRef PDBFileName;
error(Obj->getDebugPDBInfo(&D, PDBInfo, PDBFileName));
error(Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName));
DictScope PDBScope(W, "PDBInfo");
W.printHex("PDBSignature", PDBInfo->Signature);
W.printBinary("PDBGUID", makeArrayRef(PDBInfo->Guid));
W.printNumber("PDBAge", PDBInfo->Age);
W.printString("PDBFileName", PDBFileName);
W.printHex("PDBSignature", DebugInfo->Signature.CVSignature);
if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70) {
W.printBinary("PDBGUID", makeArrayRef(DebugInfo->PDB70.Signature));
W.printNumber("PDBAge", DebugInfo->PDB70.Age);
W.printString("PDBFileName", PDBFileName);
}
} else {
// FIXME: Type values of 12 and 13 are commonly observed but are not in
// the documented type enum. Figure out what they mean.