I hate to be a nag, but after several days of working on this I am still
utterly stumped.
Let me recap the situation as it currently stands: I'm trying to write code
that generates DWARF debugging information for my compiler using DIFactory
and friends. Unfortunately the information I am generating appears to be
invalid, but I can't figure out the cause.
Based on the advice in the earlier thread, I've been using dwarfdump to try
and isolate the problem. This was helpful in solving the earlier problem,
but isn't helping me with the current problem.
When I run dwarfdump -a, it prints a couple hundred pages of debug info, and
then segfaults. The last few lines before the segfault look like this:
.debug_inlined contents:
< EMPTY >
.debug_frame contents:
0x00000000: CIE
length: 0x00000010
CIE_id: 0xffffffff
version: 0x01
augmentation: ""
code_align: 1
data_align: -4
ra_register: 0x08
DW_CFA_def_cfa (esp, 4)
DW_CFA_offset (eip, 0)
DW_CFA_nop
DW_CFA_nop
Instructions: Init State: CFA=esp+4 eip=[esp+4]
0x00000014: FDE
length: 0x00000028
CIE_pointer: 0x00000000
Segmentation fault
If I grep through the output of dwarfdump, there are no other CIE or FDE
definitions that occur before this point, so I assume that the problem isn't
just this particular FDE.
One difficulty here is that I don't know which calls to DIFactory produce
these data structures. Usually my solution of last resort when dealing with
intractable debugging problems like this is to start commenting out code
until the problem goes away, but in this case I don't know where to even
start. If I comment out *all* the DWARF-generating code, then obviously the
problem goes away. :)
I did in fact discover that if I comment out all calls to
DIFactory::CreateSubprogram, the problem disappears - but then I don't have
any debugging info. (Well, I still have all the DINodes for my data
structures, just not functions.) I've also commented out all of the
declarations of parameters and local variables, which doesn't prevent the
problem from occurring. (Since my current understanding is that CIE and FDE
are used to describe the call frame, I'm trying to simplify the problem as
much as possible.)
I've carefully studied the source code of CGDebugInfo in clang as a working
example. One puzzlement is that there's a discrepancy between what the
"source level debugging with LLVM" docs say and what clang does:
According
to the docs, DW_TAG_formal_parameter is used to specify a formal parameter
in a function type descriptor, but according to a code search, the name
"DW_TAG_formal_parameter" does not appear anywhere in the clang source
code.
Instead, the argument array that is used when creating a function type
descriptor contains only the bare types, not types wrapped in a formal
parameter DIE.
However, since I've tried it both ways (wrapped and unwrapped) and the
dwarfdump crash occurs either way, this latter issue is of lesser concern.
At the moment I'm experimenting with the parameters to CreateSubprogram,
trying every possible permutation of inputs that I can think of in hope of
stumbling on the right answer. I can't think of what else to do.
Note that I am calling assert(diNode.Verify()) on every DINode after it's
created, so I know that it's valid up to that point at least. However, the
checks in Verify() aren't very extensive. (Also, I've observed in the
past
that it's kind of inconvenient that Verify() only returns a boolean result
when it fails, with no indication of what you did wrong.)
All of this is with the current LLVM head, although I was getting the same
problems with the version from about 2 months ago.
On Thu, Sep 2, 2010 at 11:43 PM, Talin <viridia at gmail.com> wrote:
> OK here's another question along these lines: According to the LLVM
source
> level debugging manual:
>
> The first member of subroutine (tag = DW_TAG_subroutine_type) type
> elements is the return type for the subroutine. The remaining elements are
> the formal arguments to the subroutine.
>
>
> Now, when I read "formal arguments" I'm assuming we're
talking about DIEs
> of type DW_TAG_formal_parameter. However, when I look in the code in
> CGDebugInfo.cpp in clang, I see that the arguments are in fact the bare
> types, not the formal parameter declarations.
>
> Here's what my code looks like:
>
> const ParameterList & params = type->params();
> for (ParameterList::const_iterator it = params.begin(); it !>
params.end(); ++it) {
> const ParameterDefn * param = *it;
> DIType ptype = genDIParameterType(param->type());
> ptype = dbgFactory_.CreateDerivedTypeEx(
> dwarf::DW_TAG_formal_parameter,
> dbgCompileUnit_,
> param->name() != NULL ? param->name() : "",
> genDIFile(param),
> getSourceLineNumber(param->location()),
> getSizeOfInBits(param->internalType()->irParameterType()),
> getInt64Val(0),
> getInt64Val(0), 0,
> ptype);
> DASSERT(ptype.Verify());
> args.push_back(ptype);
> }
>
>
> However, if I go by what's in clang, it seems that the
> DW_TAG_formal_parameter is unnecessary. Is this correct?
>
> And I'd still like to see some of these questions addressed in the
actual
> HTML documentation, as opposed to just responding here on the mailing list.
> :)
>
> On Tue, Aug 31, 2010 at 10:32 AM, Devang Patel <dpatel at apple.com>
wrote:
>
>>
>> On Aug 31, 2010, at 9:03 AM, Talin wrote:
>>
>> > 4) What is the meaning of the "inlinedAt" argument for
DebugLoc::get()?
>> Does it mean the location where the inlined code was defined, or the
>> location where it was expanded?
>>
>> the location where it was expanded
>> -
>> Devang
>
>
>
>
> --
> -- Talin
>
--
-- Talin
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20100905/8e2458cf/attachment.html>
On 5 September 2010 19:32, Talin <viridia at gmail.com> wrote:> I've carefully studied the source code of CGDebugInfo in clang as a working > example. One puzzlement is that there's a discrepancy between what the > "source level debugging with LLVM" docs say and what clang does: According > to the docs, DW_TAG_formal_parameter is used to specify a formal parameter > in a function type descriptor, but according to a code search, the name > "DW_TAG_formal_parameter" does not appear anywhere in the clang source code. > Instead, the argument array that is used when creating a function type > descriptor contains only the bare types, not types wrapped in a formal > parameter DIE.Hi Talin, Like in CGDebugInfo, you have to use the Subprogram type only for the return type. What gives you the parameters is passing the Function* as the last parameter on DIFactory.CreateSubprogram(). I suppose DIFactory was done tailored to C-like languages using Clang as the primary driver for changes. I'd not be surprised if you could do things that it didn't expect and then it'd generate images with bad Dwarf (enough to cause segfault in dwarfdump). I'd try to mimic exactly what CGDebugInfo does, even if that makes your "info func" look like C functions in GDB, or if the parameters are all mixed up. At least you get something out of it and can, then, work your way to fix it in LLVM. I'm putting together some help with using DIFactory, maybe I can turn that into a proper doc. I'll keep you posted. -- cheers, --renato http://systemcall.org/ Reclaim your digital rights, eliminate DRM, learn more at http://www.defectivebydesign.org/what_is_drm
On Sun, Sep 5, 2010 at 1:02 PM, Renato Golin <rengolin at systemcall.org>wrote:> On 5 September 2010 19:32, Talin <viridia at gmail.com> wrote: > > I've carefully studied the source code of CGDebugInfo in clang as a > working > > example. One puzzlement is that there's a discrepancy between what the > > "source level debugging with LLVM" docs say and what clang does: > According > > to the docs, DW_TAG_formal_parameter is used to specify a formal > parameter > > in a function type descriptor, but according to a code search, the name > > "DW_TAG_formal_parameter" does not appear anywhere in the clang source > code. > > Instead, the argument array that is used when creating a function type > > descriptor contains only the bare types, not types wrapped in a formal > > parameter DIE. > > Hi Talin, > > Like in CGDebugInfo, you have to use the Subprogram type only for the > return type. What gives you the parameters is passing the Function* as > the last parameter on DIFactory.CreateSubprogram(). >I understand about passing the Function* as the last argument. I'm not sure I understand the first sentance ("You have to use the Subprogram type only for the return type"). Here's what my code for creating function descriptors currently looks like (note that some parts are commented out for debugging purposes): DISubprogram CodeGenerator::genDISubprogram(const FunctionDefn * fn, Function * f) { DASSERT(fn != NULL); // Look up in the map to see if already generated. DISubprogram & sp = dbgSubprograms_[fn]; if (!sp.isSubprogram()) { DIType dbgFuncType = genDIType(fn->functionType()); DASSERT(dbgFuncType.Verify()); DASSERT(dbgCompileUnit_.Verify()); sp = dbgFactory_.CreateSubprogram( dbgCompileUnit_, fn->name(), fn->qualifiedName(), fn->linkageName(), dbgFile_, // genDIFile(fn), 1, // getSourceLineNumber(fn->location()), dbgFuncType, fn->isSynthetic() /* isLocalToUnit */, false /* isDefinition */, 0, 0 /* VK, Index */, DIType(), false /* isArtificial */, false /* isOptimized */, f); DASSERT(sp.Verify()); } return sp; } And here's the code that generates function type descriptors: DICompositeType CodeGenerator::genDIFunctionType(const FunctionType * type) { DIDescriptorArray args; args.push_back(genDIType(type->returnType())); if (type->selfParam() != NULL) { const ParameterDefn * param = type->selfParam(); // genDIParameterType() calls genDIType and then makes it a pointer // if the underlying type is a reference type. args.push_back(genDIParameterType(param->type())); } const ParameterList & params = type->params(); for (ParameterList::const_iterator it = params.begin(); it !params.end(); ++it) { const ParameterDefn * param = *it; args.push_back(genDIParameterType(param->type())); } DICompositeType fnType = dbgFactory_.CreateCompositeType( dwarf::DW_TAG_subroutine_type, dbgCompileUnit_, "", dbgFile_, 0, // Source line 0, // Size 0, // Align 0, // Offset 0, // Flags DIType(), dbgFactory_.GetOrCreateArray(args.data(), args.size())); dbgTypeMap_[type] = fnType; DASSERT(fnType.Verify()); return fnType; } I suppose DIFactory was done tailored to C-like languages using Clang> as the primary driver for changes. I'd not be surprised if you could > do things that it didn't expect and then it'd generate images with bad > Dwarf (enough to cause segfault in dwarfdump). > > I'd try to mimic exactly what CGDebugInfo does, even if that makes > your "info func" look like C functions in GDB, or if the parameters > are all mixed up. At least you get something out of it and can, then, > work your way to fix it in LLVM. > > I'm putting together some help with using DIFactory, maybe I can turn > that into a proper doc. I'll keep you posted. > > -- > cheers, > --renato > > http://systemcall.org/ > > Reclaim your digital rights, eliminate DRM, learn more at > http://www.defectivebydesign.org/what_is_drm >-- -- Talin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20100905/64d18182/attachment.html>