mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-06 01:19:28 +00:00
[PDB] Add a module descriptor for every object file
Summary: Expose the module descriptor index and fill it in for section contributions. Reviewers: zturner Subscribers: llvm-commits, ruiu, hiraditya Differential Revision: https://reviews.llvm.org/D34126 llvm-svn: 305296
This commit is contained in:
parent
41ff570657
commit
8cbdd0c0f2
@ -22,6 +22,12 @@
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace pdb {
|
||||
class DbiModuleDescriptorBuilder;
|
||||
}
|
||||
}
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
|
||||
@ -122,6 +128,12 @@ public:
|
||||
// COFF-specific and x86-only.
|
||||
std::set<SymbolBody *> SEHandlers;
|
||||
|
||||
// Pointer to the PDB module descriptor builder. Various debug info records
|
||||
// will reference object files by "module index", which is here. Things like
|
||||
// source files and section contributions are also recorded here. Will be null
|
||||
// if we are not producing a PDB.
|
||||
llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr;
|
||||
|
||||
private:
|
||||
void initializeChunks();
|
||||
void initializeSymbols();
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
|
||||
@ -53,12 +54,10 @@ using llvm::object::coff_section;
|
||||
static ExitOnError ExitOnErr;
|
||||
|
||||
// Returns a list of all SectionChunks.
|
||||
static std::vector<coff_section> getInputSections(SymbolTable *Symtab) {
|
||||
std::vector<coff_section> V;
|
||||
static void addSectionContribs(SymbolTable *Symtab, pdb::DbiStreamBuilder &DbiBuilder) {
|
||||
for (Chunk *C : Symtab->getChunks())
|
||||
if (auto *SC = dyn_cast<SectionChunk>(C))
|
||||
V.push_back(*SC->Header);
|
||||
return V;
|
||||
DbiBuilder.addSectionContrib(SC->File->ModuleDBI, SC->Header);
|
||||
}
|
||||
|
||||
static SectionChunk *findByName(std::vector<SectionChunk *> &Sections,
|
||||
@ -95,10 +94,11 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
|
||||
});
|
||||
}
|
||||
|
||||
// Merge .debug$T sections into IpiData and TpiData.
|
||||
static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
|
||||
codeview::TypeTableBuilder &TypeTable,
|
||||
codeview::TypeTableBuilder &IDTable) {
|
||||
// Add all object files to the PDB. Merge .debug$T sections into IpiData and
|
||||
// TpiData.
|
||||
static void addObjectsToPDB(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
|
||||
codeview::TypeTableBuilder &TypeTable,
|
||||
codeview::TypeTableBuilder &IDTable) {
|
||||
// Follow type servers. If the same type server is encountered more than
|
||||
// once for this instance of `PDBTypeServerHandler` (for example if many
|
||||
// object files reference the same TypeServer), the types from the
|
||||
@ -107,6 +107,20 @@ static void mergeDebugT(SymbolTable *Symtab, pdb::PDBFileBuilder &Builder,
|
||||
|
||||
// Visit all .debug$T sections to add them to Builder.
|
||||
for (ObjectFile *File : Symtab->ObjectFiles) {
|
||||
// Add a module descriptor for every object file. We need to put an absolute
|
||||
// path to the object into the PDB. If this is a plain object, we make its
|
||||
// path absolute. If it's an object in an archive, we make the archive path
|
||||
// absolute.
|
||||
bool InArchive = !File->ParentName.empty();
|
||||
SmallString<128> Path = InArchive ? File->ParentName : File->getName();
|
||||
sys::fs::make_absolute(Path);
|
||||
StringRef Name = InArchive ? File->getName() : StringRef(Path);
|
||||
File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name));
|
||||
File->ModuleDBI->setObjFileName(Path);
|
||||
|
||||
// FIXME: Walk the .debug$S sections and add them. Do things like recording
|
||||
// source files.
|
||||
|
||||
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
|
||||
if (Data.empty())
|
||||
continue;
|
||||
@ -202,17 +216,15 @@ void coff::createPDB(StringRef Path, SymbolTable *Symtab,
|
||||
InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
|
||||
|
||||
// Add an empty DPI stream.
|
||||
auto &DbiBuilder = Builder.getDbiBuilder();
|
||||
pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
|
||||
DbiBuilder.setVersionHeader(pdb::PdbDbiV110);
|
||||
|
||||
codeview::TypeTableBuilder TypeTable(BAlloc);
|
||||
codeview::TypeTableBuilder IDTable(BAlloc);
|
||||
mergeDebugT(Symtab, Builder, TypeTable, IDTable);
|
||||
addObjectsToPDB(Symtab, Builder, TypeTable, IDTable);
|
||||
|
||||
// Add Section Contributions.
|
||||
std::vector<pdb::SectionContrib> Contribs =
|
||||
pdb::DbiStreamBuilder::createSectionContribs(getInputSections(Symtab));
|
||||
DbiBuilder.setSectionContribs(Contribs);
|
||||
addSectionContribs(Symtab, DbiBuilder);
|
||||
|
||||
// Add Section Map stream.
|
||||
ArrayRef<object::coff_section> Sections = {
|
||||
|
63
lld/test/COFF/pdb-lib.s
Normal file
63
lld/test/COFF/pdb-lib.s
Normal file
@ -0,0 +1,63 @@
|
||||
# RUN: rm -rf %t && mkdir -p %t && cd %t
|
||||
# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj
|
||||
# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj
|
||||
# RUN: llvm-lib bar.obj -out:bar.lib
|
||||
# RUN: lld-link -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main
|
||||
# RUN: llvm-pdbutil raw -modules %t/foo.pdb | FileCheck %s
|
||||
|
||||
# Make sure that the PDB has module descriptors. foo.obj and bar.lib should be
|
||||
# absolute paths, and bar.obj should be the relative path passed to llvm-lib.
|
||||
|
||||
# CHECK-LABEL: Modules [
|
||||
# CHECK-NEXT: {
|
||||
# CHECK-NEXT: Name: {{.*pdb-lib.s.tmp[/\\]foo.obj}}
|
||||
# CHECK-NEXT: Debug Stream Index:
|
||||
# CHECK-NEXT: Object File Name: {{.*pdb-lib.s.tmp[/\\]foo.obj}}
|
||||
# CHECK-NEXT: Num Files: 0
|
||||
# CHECK-NEXT: Source File Name Idx: 0
|
||||
# CHECK-NEXT: Pdb File Name Idx: 0
|
||||
# CHECK-NEXT: Line Info Byte Size: 0
|
||||
# CHECK-NEXT: C13 Line Info Byte Size: 0
|
||||
# CHECK-NEXT: Symbol Byte Size: 4
|
||||
# CHECK-NEXT: Type Server Index: 0
|
||||
# CHECK-NEXT: Has EC Info: No
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: {
|
||||
# CHECK-NEXT: Name: bar.obj
|
||||
# CHECK-NEXT: Debug Stream Index:
|
||||
# CHECK-NEXT: Object File Name: {{.*pdb-lib.s.tmp[/\\]bar.lib}}
|
||||
# CHECK-NEXT: Num Files: 0
|
||||
# CHECK-NEXT: Source File Name Idx: 0
|
||||
# CHECK-NEXT: Pdb File Name Idx: 0
|
||||
# CHECK-NEXT: Line Info Byte Size: 0
|
||||
# CHECK-NEXT: C13 Line Info Byte Size: 0
|
||||
# CHECK-NEXT: Symbol Byte Size: 4
|
||||
# CHECK-NEXT: Type Server Index: 0
|
||||
# CHECK-NEXT: Has EC Info: No
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: {
|
||||
# CHECK-NEXT: Name: * Linker *
|
||||
# CHECK-NEXT: Debug Stream Index:
|
||||
# CHECK-NEXT: Object File Name:
|
||||
# CHECK-NEXT: Num Files: 0
|
||||
# CHECK-NEXT: Source File Name Idx: 0
|
||||
# CHECK-NEXT: Pdb File Name Idx: 0
|
||||
# CHECK-NEXT: Line Info Byte Size: 0
|
||||
# CHECK-NEXT: C13 Line Info Byte Size: 0
|
||||
# CHECK-NEXT: Symbol Byte Size: 4
|
||||
# CHECK-NEXT: Type Server Index: 0
|
||||
# CHECK-NEXT: Has EC Info: No
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
||||
|
||||
|
||||
.def _main;
|
||||
.scl 2;
|
||||
.type 32;
|
||||
.endef
|
||||
.globl _main
|
||||
_main:
|
||||
calll _bar
|
||||
xor %eax, %eax
|
||||
retl
|
||||
|
@ -2,6 +2,7 @@
|
||||
# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj
|
||||
|
||||
; If /DEBUG is not specified, /pdb is ignored.
|
||||
# RUN: rm -f %t.pdb
|
||||
# RUN: lld-link /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj
|
||||
# RUN: not ls %t.pdb
|
||||
|
||||
|
@ -191,8 +191,34 @@
|
||||
# RAW-NEXT: mspdb00.dll version: 0.0.0
|
||||
# RAW-NEXT: Modules [
|
||||
# RAW-NEXT: {
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Name: {{.*}}tmp1.obj
|
||||
# RAW-NEXT: Debug Stream Index: 9
|
||||
# RAW-NEXT: Object File Name: {{.*}}tmp1.obj
|
||||
# RAW-NEXT: Num Files: 0
|
||||
# RAW-NEXT: Source File Name Idx: 0
|
||||
# RAW-NEXT: Pdb File Name Idx: 0
|
||||
# RAW-NEXT: Line Info Byte Size: 0
|
||||
# RAW-NEXT: C13 Line Info Byte Size: 0
|
||||
# RAW-NEXT: Symbol Byte Size: 4
|
||||
# RAW-NEXT: Type Server Index: 0
|
||||
# RAW-NEXT: Has EC Info: No
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: {
|
||||
# RAW-NEXT: Name: {{.*}}tmp2.obj
|
||||
# RAW-NEXT: Debug Stream Index: 10
|
||||
# RAW-NEXT: Object File Name: {{.*}}tmp2.obj
|
||||
# RAW-NEXT: Num Files: 0
|
||||
# RAW-NEXT: Source File Name Idx: 0
|
||||
# RAW-NEXT: Pdb File Name Idx: 0
|
||||
# RAW-NEXT: Line Info Byte Size: 0
|
||||
# RAW-NEXT: C13 Line Info Byte Size: 0
|
||||
# RAW-NEXT: Symbol Byte Size: 4
|
||||
# RAW-NEXT: Type Server Index: 0
|
||||
# RAW-NEXT: Has EC Info: No
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: {
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Debug Stream Index: 11
|
||||
# RAW-NEXT: Object File Name:
|
||||
# RAW-NEXT: Num Files: 0
|
||||
# RAW-NEXT: Source File Name Idx: 0
|
||||
@ -207,7 +233,7 @@
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Section Contributions [
|
||||
# RAW-NEXT: Contribution {
|
||||
# RAW-NEXT: ISect: 0
|
||||
# RAW-NEXT: ISect: 65535
|
||||
# RAW-NEXT: Off: 1288
|
||||
# RAW-NEXT: Size: 14
|
||||
# RAW-NEXT: Characteristics [ (0x60500020)
|
||||
@ -218,13 +244,13 @@
|
||||
# RAW-NEXT: ]
|
||||
# RAW-NEXT: Module {
|
||||
# RAW-NEXT: Index: 0
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Name: {{.*}}tmp1.obj
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Data CRC: 0
|
||||
# RAW-NEXT: Reloc CRC: 0
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Contribution {
|
||||
# RAW-NEXT: ISect: 0
|
||||
# RAW-NEXT: ISect: 65535
|
||||
# RAW-NEXT: Off: 1312
|
||||
# RAW-NEXT: Size: 8
|
||||
# RAW-NEXT: Characteristics [ (0x40300040)
|
||||
@ -234,13 +260,13 @@
|
||||
# RAW-NEXT: ]
|
||||
# RAW-NEXT: Module {
|
||||
# RAW-NEXT: Index: 0
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Name: {{.*}}tmp1.obj
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Data CRC: 0
|
||||
# RAW-NEXT: Reloc CRC: 0
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Contribution {
|
||||
# RAW-NEXT: ISect: 0
|
||||
# RAW-NEXT: ISect: 65535
|
||||
# RAW-NEXT: Off: 1320
|
||||
# RAW-NEXT: Size: 12
|
||||
# RAW-NEXT: Characteristics [ (0x40300040)
|
||||
@ -250,13 +276,13 @@
|
||||
# RAW-NEXT: ]
|
||||
# RAW-NEXT: Module {
|
||||
# RAW-NEXT: Index: 0
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Name: {{.*}}tmp1.obj
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Data CRC: 0
|
||||
# RAW-NEXT: Reloc CRC: 0
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Contribution {
|
||||
# RAW-NEXT: ISect: 0
|
||||
# RAW-NEXT: ISect: 65535
|
||||
# RAW-NEXT: Off: 1144
|
||||
# RAW-NEXT: Size: 6
|
||||
# RAW-NEXT: Characteristics [ (0x60500020)
|
||||
@ -266,8 +292,8 @@
|
||||
# RAW-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
|
||||
# RAW-NEXT: ]
|
||||
# RAW-NEXT: Module {
|
||||
# RAW-NEXT: Index: 0
|
||||
# RAW-NEXT: Name: * Linker *
|
||||
# RAW-NEXT: Index: 1
|
||||
# RAW-NEXT: Name: {{.*}}tmp2.obj
|
||||
# RAW-NEXT: }
|
||||
# RAW-NEXT: Data CRC: 0
|
||||
# RAW-NEXT: Reloc CRC: 0
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
StringRef getModuleName() const { return ModuleName; }
|
||||
StringRef getObjFileName() const { return ObjFileName; }
|
||||
|
||||
unsigned getModuleIndex() const { return Layout.Mod; }
|
||||
|
||||
ArrayRef<std::string> source_files() const {
|
||||
return makeArrayRef(SourceFiles);
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ public:
|
||||
void setPdbDllRbld(uint16_t R);
|
||||
void setFlags(uint16_t F);
|
||||
void setMachineType(PDB_Machine M);
|
||||
void setSectionContribs(ArrayRef<SectionContrib> SecMap);
|
||||
void setSectionMap(ArrayRef<SecMapEntry> SecMap);
|
||||
|
||||
// Add given bytes as a new stream.
|
||||
@ -65,10 +64,8 @@ public:
|
||||
|
||||
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
|
||||
|
||||
// A helper function to create Section Contributions from COFF input
|
||||
// section headers.
|
||||
static std::vector<SectionContrib>
|
||||
createSectionContribs(ArrayRef<llvm::object::coff_section> SecHdrs);
|
||||
void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
|
||||
const llvm::object::coff_section *SecHdr);
|
||||
|
||||
// A helper function to create a Section Map from a COFF section header.
|
||||
static std::vector<SecMapEntry>
|
||||
@ -112,7 +109,7 @@ private:
|
||||
|
||||
WritableBinaryStreamRef NamesBuffer;
|
||||
MutableBinaryByteStream FileInfoBuffer;
|
||||
ArrayRef<SectionContrib> SectionContribs;
|
||||
std::vector<SectionContrib> SectionContribs;
|
||||
ArrayRef<SecMapEntry> SectionMap;
|
||||
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
|
||||
};
|
||||
|
@ -45,10 +45,6 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
|
||||
|
||||
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
|
||||
|
||||
void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
|
||||
SectionContribs = Arr;
|
||||
}
|
||||
|
||||
void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
|
||||
SectionMap = SecMap;
|
||||
}
|
||||
@ -293,23 +289,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) {
|
||||
return Ret;
|
||||
}
|
||||
|
||||
// A utility function to create Section Contributions
|
||||
// for a given input sections.
|
||||
std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
|
||||
ArrayRef<object::coff_section> SecHdrs) {
|
||||
std::vector<SectionContrib> Ret;
|
||||
|
||||
// Create a SectionContrib for each input section.
|
||||
for (auto &Sec : SecHdrs) {
|
||||
Ret.emplace_back();
|
||||
auto &Entry = Ret.back();
|
||||
memset(&Entry, 0, sizeof(Entry));
|
||||
|
||||
Entry.Off = Sec.PointerToRawData;
|
||||
Entry.Size = Sec.SizeOfRawData;
|
||||
Entry.Characteristics = Sec.Characteristics;
|
||||
}
|
||||
return Ret;
|
||||
void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
|
||||
const object::coff_section *SecHdr) {
|
||||
SectionContrib SC;
|
||||
memset(&SC, 0, sizeof(SC));
|
||||
SC.ISect = (uint16_t)~0U; // This represents nil.
|
||||
SC.Off = SecHdr->PointerToRawData;
|
||||
SC.Size = SecHdr->SizeOfRawData;
|
||||
SC.Characteristics = SecHdr->Characteristics;
|
||||
// Use the module index in the module dbi stream or nil (-1).
|
||||
SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U;
|
||||
SectionContribs.emplace_back(SC);
|
||||
}
|
||||
|
||||
// A utility function to create a Section Map for a given list of COFF sections.
|
||||
@ -372,7 +362,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
|
||||
if (!SectionContribs.empty()) {
|
||||
if (auto EC = Writer.writeEnum(DbiSecContribVer60))
|
||||
return EC;
|
||||
if (auto EC = Writer.writeArray(SectionContribs))
|
||||
if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs)))
|
||||
return EC;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user