Skip to content

Commit

Permalink
CodeView: extract the OMF Directory Header
Browse files Browse the repository at this point in the history
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
  • Loading branch information
compnerd committed Aug 9, 2016
1 parent f7c3c99 commit b79146f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 28 deletions.
55 changes: 55 additions & 0 deletions include/llvm/DebugInfo/CodeView/CVDebugRecord.h
Original file line number Diff line number Diff line change
@@ -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

14 changes: 3 additions & 11 deletions include/llvm/Object/COFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -868,14 +860,14 @@ class COFFObjectFile : public ObjectFile {

/// 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;
Expand Down
6 changes: 3 additions & 3 deletions lib/DebugInfo/Symbolize/Symbolize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 10 additions & 8 deletions lib/Object/COFFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,26 +487,28 @@ 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.
PDBFileName = PDBFileName.split('\0').first;
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);
Expand Down
14 changes: 8 additions & 6 deletions tools/llvm-readobj/COFFDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit b79146f

Please sign in to comment.