Index: lit/Modules/PECOFF/export-dllfunc.yaml =================================================================== --- lit/Modules/PECOFF/export-dllfunc.yaml +++ lit/Modules/PECOFF/export-dllfunc.yaml @@ -1,11 +1,15 @@ # REQUIRES: lld # RUN: yaml2obj < %s > %t.obj # -# RUN: lld-link /machine:x64 /out:%t.dll /noentry /nodefaultlib /dll %t.obj /export:DllFunc +# RUN: lld-link /machine:x64 /out:%t.dll /noentry /nodefaultlib /debug /dll %t.obj /export:DllFunc # # RUN: lldb-test object-file %t.dll | FileCheck -check-prefix=BASIC-CHECK %s # RUN: lldb-test object-file -dep-modules %t.dll | FileCheck -check-prefix=DEPS %s +# BASIC-CHECK: Plugin name: pe-coff + +# UUID should not be empty if the module is built with debug info. +# BASIC-CHECK-DAG: UUID: {{[0-9A-F]{7,}[0-9A-F]}}-{{.*}} # BASIC-CHECK: Showing 3 subsections # BASIC-CHECK: Index: 0 Index: lit/Modules/PECOFF/uuid.yaml =================================================================== --- /dev/null +++ lit/Modules/PECOFF/uuid.yaml @@ -0,0 +1,90 @@ +# REQUIRES: lld +# RUN: yaml2obj %s > %t.obj +# RUN: lldb-test object-file %t.obj | FileCheck %s + +# CHECK-DAG: UUID: 14B292E0-D81A-B4F1-4C4C-44205044422E-00000001 + +--- !COFF +OptionalHeader: + AddressOfEntryPoint: 0 + ImageBase: 2147483648 + SectionAlignment: 4096 + FileAlignment: 512 + MajorOperatingSystemVersion: 6 + MinorOperatingSystemVersion: 0 + MajorImageVersion: 0 + MinorImageVersion: 0 + MajorSubsystemVersion: 6 + MinorSubsystemVersion: 0 + Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI + DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ] + SizeOfStackReserve: 1048576 + SizeOfStackCommit: 4096 + SizeOfHeapReserve: 1048576 + SizeOfHeapCommit: 4096 + ExportTable: + RelativeVirtualAddress: 8327 + Size: 90 + ImportTable: + RelativeVirtualAddress: 0 + Size: 0 + ResourceTable: + RelativeVirtualAddress: 0 + Size: 0 + ExceptionTable: + RelativeVirtualAddress: 12288 + Size: 12 + CertificateTable: + RelativeVirtualAddress: 0 + Size: 0 + BaseRelocationTable: + RelativeVirtualAddress: 0 + Size: 0 + Debug: + RelativeVirtualAddress: 8192 + Size: 28 + Architecture: + RelativeVirtualAddress: 0 + Size: 0 + GlobalPtr: + RelativeVirtualAddress: 0 + Size: 0 + TlsTable: + RelativeVirtualAddress: 0 + Size: 0 + LoadConfigTable: + RelativeVirtualAddress: 0 + Size: 0 + BoundImport: + RelativeVirtualAddress: 0 + Size: 0 + IAT: + RelativeVirtualAddress: 0 + Size: 0 + DelayImportDescriptor: + RelativeVirtualAddress: 0 + Size: 0 + ClrRuntimeHeader: + RelativeVirtualAddress: 0 + Size: 0 +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + VirtualAddress: 4096 + VirtualSize: 22 + SectionData: 50894C24048B4C24040FAF4C2404890C248B042459C3 + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 8192 + VirtualSize: 236 + SectionData: 00000000A565B65C00000000020000006B0000001C2000001C06000052534453E092B2141AD8F1B44C4C44205044422E01000000443A5C757073747265616D5C6275696C645C746F6F6C735C6C6C64625C6C69745C4D6F64756C65735C5045434F46465C4F75747075745C6578706F72742D646C6C66756E632E79616D6C2E746D702E70646200000000000000000000000000AF200000000000000200000001000000CB200000D3200000D72000006578706F72742D646C6C66756E632E79616D6C2E746D702E646C6C000000000000100000D92000000100446C6C46756E63000000000101010001020000 + - Name: .pdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 12288 + VirtualSize: 12 + SectionData: '0010000016100000E4200000' +symbols: [] +... Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -286,6 +286,7 @@ llvm::Optional m_deps_filespec; typedef llvm::object::OwningBinary OWNBINType; llvm::Optional m_owningbin; + lldb_private::UUID m_uuid; }; #endif // liblldb_ObjectFilePECOFF_h_ Index: source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp =================================================================== --- source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -40,6 +40,54 @@ using namespace lldb; using namespace lldb_private; +struct CVInfoPdb70 { + // 16-byte GUID + struct _Guid { + llvm::support::ulittle32_t Data1; + llvm::support::ulittle16_t Data2; + llvm::support::ulittle16_t Data3; + uint8_t Data4[8]; + } Guid; + + llvm::support::ulittle32_t Age; +}; + +static UUID GetCoffUUID(llvm::object::COFFObjectFile *coff_obj) { + if (!coff_obj) + return UUID(); + + const llvm::codeview::DebugInfo *pdb_info = nullptr; + llvm::StringRef pdb_file; + + // This part is similar with what has done in minidump parser. + if (!coff_obj->getDebugPDBInfo(pdb_info, pdb_file) && pdb_info) { + if (pdb_info->PDB70.CVSignature == llvm::OMF::Signature::PDB70) { + using llvm::support::endian::read16be; + using llvm::support::endian::read32be; + + const uint8_t *sig = pdb_info->PDB70.Signature; + struct CVInfoPdb70 info; + info.Guid.Data1 = read32be(sig); + sig += 4; + info.Guid.Data2 = read16be(sig); + sig += 2; + info.Guid.Data3 = read16be(sig); + sig += 2; + memcpy(info.Guid.Data4, sig, 8); + + // Return 20-byte UUID if the Age is not zero + if (pdb_info->PDB70.Age) { + info.Age = read32be(&pdb_info->PDB70.Age); + return UUID::fromOptionalData(&info, sizeof(info)); + } + // Otherwise return 16-byte GUID + return UUID::fromOptionalData(&info.Guid, sizeof(info.Guid)); + } + } + + return UUID(); +} + void ObjectFilePECOFF::Initialize() { PluginManager::RegisterPlugin( GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, @@ -113,36 +161,43 @@ lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); + if (!data_sp || !ObjectFilePECOFF::MagicBytesMatch(data_sp)) + return initial_count; - if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) { - DataExtractor data; - data.SetData(data_sp, data_offset, length); - data.SetByteOrder(eByteOrderLittle); + auto binary = llvm::object::createBinary(file.GetPath()); + if (!binary) + return initial_count; - dos_header_t dos_header; - coff_header_t coff_header; + if (!binary->getBinary()->isCOFF() && + !binary->getBinary()->isCOFFImportFile()) + return initial_count; - if (ParseDOSHeader(data, dos_header)) { - lldb::offset_t offset = dos_header.e_lfanew; - uint32_t pe_signature = data.GetU32(&offset); - if (pe_signature != IMAGE_NT_SIGNATURE) - return false; - if (ParseCOFFHeader(data, &offset, coff_header)) { - ArchSpec spec; - if (coff_header.machine == MachineAmd64) { - spec.SetTriple("x86_64-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } else if (coff_header.machine == MachineX86) { - spec.SetTriple("i386-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - spec.SetTriple("i686-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } else if (coff_header.machine == MachineArmNt) { - spec.SetTriple("arm-pc-windows"); - specs.Append(ModuleSpec(file, spec)); - } - } - } + auto COFFObj = + llvm::cast(binary->getBinary()); + + ModuleSpec module_spec(file); + ArchSpec &spec = module_spec.GetArchitecture(); + lldb_private::UUID &uuid = module_spec.GetUUID(); + if (!uuid.IsValid()) + uuid = GetCoffUUID(COFFObj); + + switch (COFFObj->getMachine()) { + case MachineAmd64: + spec.SetTriple("x86_64-pc-windows"); + specs.Append(module_spec); + break; + case MachineX86: + spec.SetTriple("i386-pc-windows"); + specs.Append(module_spec); + spec.SetTriple("i686-pc-windows"); + specs.Append(module_spec); + break; + case MachineArmNt: + spec.SetTriple("arm-pc-windows"); + specs.Append(module_spec); + break; + default: + break; } return specs.GetSize() - initial_count; @@ -828,7 +883,19 @@ } } -UUID ObjectFilePECOFF::GetUUID() { return UUID(); } +UUID ObjectFilePECOFF::GetUUID() { + if (m_uuid.IsValid()) + return m_uuid; + + if (!CreateBinary()) + return UUID(); + + auto COFFObj = + llvm::cast(m_owningbin->getBinary()); + + m_uuid = GetCoffUUID(COFFObj); + return m_uuid; +} uint32_t ObjectFilePECOFF::ParseDependentModules() { ModuleSP module_sp(GetModule()); @@ -850,8 +917,7 @@ static_cast(this), static_cast(module_sp.get()), module_sp->GetSpecificationDescription().c_str(), static_cast(m_owningbin.getPointer()), - m_owningbin ? static_cast(m_owningbin->getBinary()) - : nullptr); + static_cast(m_owningbin->getBinary())); auto COFFObj = llvm::dyn_cast(m_owningbin->getBinary()); @@ -912,7 +978,8 @@ if (!section_list) m_entry_point_address.SetOffset(file_addr); else - m_entry_point_address.ResolveAddressUsingFileSections(file_addr, section_list); + m_entry_point_address.ResolveAddressUsingFileSections(file_addr, + section_list); return m_entry_point_address; }