[DebugInfo] DWARF C API

Hi folks,

I am trying to implement the C bindings API for DebugInfo::DWARF::DWARFDie. My goal is to have a C library that reads and parses DWARF debugging format (just like how llvm-dwarfdump does, but maybe more than just dumping debug info)

I’ve started with creating C structure for DebugInfo::DWARF::DWARFContext which contains all DWARF DIEs in the object file. For this I used


DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DWARFContext, LLVMDWARFContextRef)

then defined some C functions


LLVMDWARFContextRef LLVMCreateDWARFContext(LLVMBinaryRef Bin) {
std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*unwrap(Bin));
return wrap(DICtx.release());
}

void LLVMPrintDWARFContext(LLVMDWARFContextRef C) {
DIDumpOptions DumpOpts;
DumpOpts.DumpType = DIDT_DebugInfo; // I only care about the .debug_info section

unwrap(C)->dump(outs(), DumpOpts);
}

However, I got a segfault when trying to dump the LLVMDWARFContextRef using the second function. More precisely, it segfaulted when dumping the attribute of the DWARFDie.

I tried to do this instead to see if the wrapping/unwrapping has bugs


LLVMDWARFContextRef LLVMCreateDWARFContext(LLVMBinaryRef Bin) {
std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*unwrap(Bin));
LLVMDWARFContextRef C = wrap(DICtx.release());
LLVMPrintDWARFContext(C);
return C;

}

and the call to LLVMPrintDWARFContext did not segfault this time.

Can anybody who knows about DWARFContext and DWARFDie tell me what I did wrong? Or is it a bug in DWARFDie::dump() method?

Thank you very much for your help,

Might be worth running under valgrind or the LLVM sanitizers? (could
help diagnose what's going wrong more specifically than a segfault)

Hi David,

Sorry, I forget to attach the valgrind dump to this. I was not sure if my implementation was ok, so I wanted to ask if I’ve done something wrong first.

Process terminating with default action of signal 11 (SIGSEGV)
Access not within mapped region at address 0xB
at 0x54F4516: llvm::object::COFFObjectFile::moveSectionNext(llvm::object::DataRefImpl&) const (COFFObjectFile.cpp:267)
by 0x55A62FB: llvm::object::ObjectFile::isBerkeleyText(llvm::object::DataRefImpl) const (ObjectFile.cpp:80)
by 0x5538CF9: llvm::object::RelocationRef::getType() const (ObjectFile.h:543)
by 0x55AE53E: llvm::object::resolveARM(llvm::object::RelocationRef, unsigned long, unsigned long) (RelocationResolver.cpp:250)
by 0x502802B: llvm::DWARFDataExtractor::getRelocatedValue(unsigned int, unsigned int*, unsigned long*) const (DWARFDataExtractor.cpp:27)
by 0x5071C2F: llvm::DWARFUnitHeader::extract(llvm::DWARFContext&, llvm::DWARFDataExtractor const&, unsigned int*, llvm::DWARFSectionKind, llvm::DWARFUnitIndex const*, llvm::DWARFUnitIndex::Entr y const*) (DWARFUnit.cpp:254)
by 0x5070BAD: llvm::DWARFUnitVector::addUnitsImpl(llvm::DWARFContext&, llvm::DWARFObject const&, llvm::DWARFSection const&, llvm::DWARFDebugAbbrev const*, llvm::DWARFSection const*, llvm::DWARF Section const*, llvm::StringRef, llvm::DWARFSection const&, llvm::DWARFSection const*, llvm::DWARFSection const&, bool, bool, bool, llvm::DWARFSectionKind)::{lambda(unsigned int, llvm::DWARFSectionKind, llvm ::DWARFSection const*, llvm::DWARFUnitIndex::Entry const*)#1}::operator()(unsigned int, llvm::DWARFSectionKind, llvm::DWARFSection const*, llvm::DWARFUnitIndex::Entry const*) const (DWARFUnit.cpp:82)

by 0x50751E1: std::_Function_handler<std::unique_ptr<llvm::DWARFUnit, std::default_deletellvm::DWARFUnit > (unsigned int, llvm::DWARFSectionKind, llvm::DWARFSection const*, llvm::DWARFUnitInd ex::Entry const*), llvm::DWARFUnitVector::addUnitsImpl(llvm::DWARFContext&, llvm::DWARFObject const&, llvm::DWARFSection const&, llvm::DWARFDebugAbbrev const*, llvm::DWARFSection const*, llvm::DWARFSection c onst*, llvm::StringRef, llvm::DWARFSection const&, llvm::DWARFSection const*, llvm::DWARFSection const&, bool, bool, bool, llvm::DWARFSectionKind)::{lambda(unsigned int, llvm::DWARFSectionKind, llvm::DWARFSe ction const*, llvm::DWARFUnitIndex::Entry const*)#1}>::_M_invoke(std::_Any_data const&, unsigned int, llvm::DWARFSectionKind, llvm::DWARFSection const*, llvm::DWARFUnitIndex::Entry const*) (functional:2057)

by 0x507656E: std::function<std::unique_ptr<llvm::DWARFUnit, std::default_deletellvm::DWARFUnit > (unsigned int, llvm::DWARFSectionKind, llvm::DWARFSection const*, llvm::DWARFUnitIndex::Entry const*)>::operator()(unsigned int, llvm::DWARFSectionKind, llvm::DWARFSection const*, llvm::DWARFUnitIndex::Entry const*) const (functional:2471)

by 0x5070FE6: llvm::DWARFUnitVector::addUnitsImpl(llvm::DWARFContext&, llvm::DWARFObject const&, llvm::DWARFSection const&, llvm::DWARFDebugAbbrev const*, llvm::DWARFSection const*, llvm::DWARF Section const*, llvm::StringRef, llvm::DWARFSection const&, llvm::DWARFSection const*, llvm::DWARFSection const&, bool, bool, bool, llvm::DWARFSectionKind) (DWARFUnit.cpp:111)

by 0x50708CF: llvm::DWARFUnitVector::addUnitsForSection(llvm::DWARFContext&, llvm::DWARFSection const&, llvm::DWARFSectionKind) (DWARFUnit.cpp:44)
by 0x5000AAE: llvm::DWARFContext::parseNormalUnits()::{lambda(llvm::DWARFSection const&)#1}::operator()(llvm::DWARFSection const&) const (DWARFContext.cpp:881)

However, I can’t see how this error can relate to the wrapping/unwrapping macros generating C structure?

Thanks a lot for your time

Sounds to me like the DWARFContext might not have a valid
reference/pointer/whatever to the ObjectFile? Is there a chance the
ObjectFile pointer in the DWARFContext is null?

I'd suggest you poke around in a debugger there to check what state
it's in in a good (non-C-wrapped) example and in the C-wrapped example
to compare/contrast.

Wow I figured it out. Thanks for your input David :slight_smile: