operator overloading fails while debugging with gdb for i386

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

operator overloading fails while debugging with gdb for i386

Mayur Pandey
For the given test: 

class A1 {
  int x;
  int y;

  public:

  A1(int a, int b)
  {
   x=a;
   y=b;
  }

A1 operator+(const A1&);
};


A1 A1::operator+(const A1& second)
{
 A1 sum(0,0);
 sum.x = x + second.x;
 sum.y = y + second.y;

 return (sum);
}


int main (void)
{
 A1 one(2,3);
 A1 two(4,5);

 return 0;
}


when the exectable of this code is debugged in gdb for i386, we dont get the
expected results.

when we break at return 0; and give the command: print one + two, the result
should be $1 = {x = 6, y = 8}, but the result obtained is $1 = {x = 2, y = 3}.

This is related to debug information generated, as normally the overloading is
occuring.
eg: A1 three = one + two results {x = 6, y = 8}.


On checking the assembly, a suspicious entry is found which may be related for
the failure:

    #DEBUG_VALUE: operator+:this <- undef
    #DEBUG_VALUE: operator+:second <- undef


--
Thanx & Regards
Mayur Pandey


 
 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Mayur Pandey
Problem seems not only with operator overloading,  It occurs with struct value returning also.

gdb while debugging expects the return value in eax, gcc does returns in eax, But Clang returns in edx(it can be checked in gdb by printing the contents of edx).

Code(sample code)

struct A1 {
  int x;
  int y;
};

A1 sum(const A1 one, const A1 two)
{
 A1 plus = {0,0};
 plus.x = one.x + two.x;
 plus.y = one.y + two.y;

 return (plus);
}


int main (void)
{
 A1 one= {2,3};
 A1 two= {4,5};
 A1 three = sum(one,two);
 return 0;
}


gcc assembley (snippet of sum function)

_Z3sum2A1S_:
    .loc 1 8 0
    pushl    %ebp
    movl    %esp, %ebp
    .loc 1 9 0
    movl    8(%ebp), %eax
    movl    $0, (%eax)
    movl    8(%ebp), %eax
    movl    $0, 4(%eax)
    .loc 1 10 0
    movl    12(%ebp), %edx
    movl    20(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, (%eax)
    .loc 1 11 0
    movl    16(%ebp), %edx
    movl    24(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, 4(%eax)
.LBE2:
    .loc 1 14 0
    movl    8(%ebp), %eax
    popl    %ebp
    ret    $4

clang assembly (snippet of sum function)
_Z3sum2A1S_:                          
   .loc    1 8 0                
    pushl    %edi
    pushl    %esi
    leal    24(%esp), %eax
    leal    16(%esp), %ecx
    movl    12(%esp), %edx
    .loc    1 9 17 prologue_end    
    movl    $0, 4(%edx)
    movl    $0, (%edx)
    .loc    1 10 2                 
    movl    (%ecx), %esi
    movl    (%eax), %edi
    addl    %edi, %esi
    movl    %esi, (%edx)
    .loc    1 11 2                 
    movl    4(%ecx), %ecx
    movl    4(%eax), %eax
    addl    %eax, %ecx
    movl    %ecx, 4(%edx)
    .loc    1 13 2                 
    popl    %esi
    popl    %edi
    ret    $4


But while returning int value clang returns with eax... as expect. Problem comes with when used struct/class

Is the behaviour of llvm as per the standards or is this a bug??









On Thu, Nov 29, 2012 at 12:40 PM, Mayur Pandey <[hidden email]> wrote:
For the given test: 

class A1 {
  int x;
  int y;

  public:

  A1(int a, int b)
  {
   x=a;
   y=b;
  }

A1 operator+(const A1&);
};


A1 A1::operator+(const A1& second)
{
 A1 sum(0,0);
 sum.x = x + second.x;
 sum.y = y + second.y;

 return (sum);
}


int main (void)
{
 A1 one(2,3);
 A1 two(4,5);

 return 0;
}


when the exectable of this code is debugged in gdb for i386, we dont get the
expected results.

when we break at return 0; and give the command: print one + two, the result
should be $1 = {x = 6, y = 8}, but the result obtained is $1 = {x = 2, y = 3}.

This is related to debug information generated, as normally the overloading is
occuring.
eg: A1 three = one + two results {x = 6, y = 8}.


On checking the assembly, a suspicious entry is found which may be related for
the failure:

    #DEBUG_VALUE: operator+:this <- undef
    #DEBUG_VALUE: operator+:second <- undef


--
Thanx & Regards
Mayur Pandey


 
 




--
Thanx & Regards
Mayur Pandey


 
 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

James Molloy-3
Hi,

Structures are passed by pointer, so the return value is not actually in eax. That code gets transformed into something like:

void sum(A1 *out, const A1 one, const A1 two) {
  out->x = one.x + two.x
  out->y = one.y + two.y
}

So actually the function ends up returning void and operating on a hidden parameter, so %eax is dead at the end of the function and should not be being relied upon by the calling code.

I believe this is a red-herring to whatever your actual bug is.

Cheers,

James
________________________________________
From: [hidden email] [[hidden email]] On Behalf Of Mayur Pandey [[hidden email]]
Sent: 01 December 2012 11:13
To: [hidden email]
Subject: Re: [LLVMdev] operator overloading fails while debugging with gdb      for i386

Problem seems not only with operator overloading,  It occurs with struct value returning also.

gdb while debugging expects the return value in eax, gcc does returns in eax, But Clang returns in edx(it can be checked in gdb by printing the contents of edx).

Code(sample code)

struct A1 {
  int x;
  int y;
};

A1 sum(const A1 one, const A1 two)
{
 A1 plus = {0,0};
 plus.x = one.x + two.x;
 plus.y = one.y + two.y;

 return (plus);
}


int main (void)
{
 A1 one= {2,3};
 A1 two= {4,5};
 A1 three = sum(one,two);
 return 0;
}


gcc assembley (snippet of sum function)

_Z3sum2A1S_:
    .loc 1 8 0
    pushl    %ebp
    movl    %esp, %ebp
    .loc 1 9 0
    movl    8(%ebp), %eax
    movl    $0, (%eax)
    movl    8(%ebp), %eax
    movl    $0, 4(%eax)
    .loc 1 10 0
    movl    12(%ebp), %edx
    movl    20(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, (%eax)
    .loc 1 11 0
    movl    16(%ebp), %edx
    movl    24(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, 4(%eax)
.LBE2:
    .loc 1 14 0
    movl    8(%ebp), %eax
    popl    %ebp
    ret    $4

clang assembly (snippet of sum function)
_Z3sum2A1S_:
   .loc    1 8 0
    pushl    %edi
    pushl    %esi
    leal    24(%esp), %eax
    leal    16(%esp), %ecx
    movl    12(%esp), %edx
    .loc    1 9 17 prologue_end
    movl    $0, 4(%edx)
    movl    $0, (%edx)
    .loc    1 10 2
    movl    (%ecx), %esi
    movl    (%eax), %edi
    addl    %edi, %esi
    movl    %esi, (%edx)
    .loc    1 11 2
    movl    4(%ecx), %ecx
    movl    4(%eax), %eax
    addl    %eax, %ecx
    movl    %ecx, 4(%edx)
    .loc    1 13 2
    popl    %esi
    popl    %edi
    ret    $4


But while returning int value clang returns with eax... as expect. Problem comes with when used struct/class

Is the behaviour of llvm as per the standards or is this a bug??









On Thu, Nov 29, 2012 at 12:40 PM, Mayur Pandey <[hidden email]<mailto:[hidden email]>> wrote:


For the given test:

class A1 {
  int x;
  int y;

  public:

  A1(int a, int b)
  {
   x=a;
   y=b;
  }

A1 operator+(const A1&);
};


A1 A1::operator+(const A1& second)
{
 A1 sum(0,0);
 sum.x = x + second.x;
 sum.y = y + second.y;

 return (sum);
}


int main (void)
{
 A1 one(2,3);
 A1 two(4,5);

 return 0;
}


when the exectable of this code is debugged in gdb for i386, we dont get the
expected results.

when we break at return 0; and give the command: print one + two, the result
should be $1 = {x = 6, y = 8}, but the result obtained is $1 = {x = 2, y = 3}.

This is related to debug information generated, as normally the overloading is
occuring.
eg: A1 three = one + two results {x = 6, y = 8}.


On checking the assembly, a suspicious entry is found which may be related for
the failure:

    #DEBUG_VALUE: operator+:this <- undef
    #DEBUG_VALUE: operator+:second <- undef


--
Thanx & Regards
Mayur Pandey








--
Thanx & Regards
Mayur Pandey







_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Mayur Pandey
Hi,

   As you told that function ends up returning void, I just confirmed it in the IR, the function is defined as:

define void @_Z3sum2A1S_(%struct.A1* noalias sret %agg.result, %struct.A1* byval align 4 %one, %struct.A1* byval align 4 %two).

But when i checked the register values in g++, eax contains an address of stack, which points to the value (object) returned by sum. That is if we print the contents of the address stored in eax and contents of (address stored in eax)+4, we get the correct value of sum. And GDB seems to print from this only when we give the command print sum(one,two). { for clang compiled code eax has some other value}

So is this just a coincidence for g++ that eax points to this address and gdb prints the right value on the command print sum(one,two)??



On Sat, Dec 1, 2012 at 9:42 PM, James Molloy <[hidden email]> wrote:
Hi,

Structures are passed by pointer, so the return value is not actually in eax. That code gets transformed into something like:

void sum(A1 *out, const A1 one, const A1 two) {
  out->x = one.x + two.x
  out->y = one.y + two.y
}

So actually the function ends up returning void and operating on a hidden parameter, so %eax is dead at the end of the function and should not be being relied upon by the calling code.

I believe this is a red-herring to whatever your actual bug is.

Cheers,

James
________________________________________
From: [hidden email] [[hidden email]] On Behalf Of Mayur Pandey [[hidden email]]
Sent: 01 December 2012 11:13
To: [hidden email]
Subject: Re: [LLVMdev] operator overloading fails while debugging with gdb      for i386

Problem seems not only with operator overloading,  It occurs with struct value returning also.

gdb while debugging expects the return value in eax, gcc does returns in eax, But Clang returns in edx(it can be checked in gdb by printing the contents of edx).

Code(sample code)

struct A1 {
  int x;
  int y;
};

A1 sum(const A1 one, const A1 two)
{
 A1 plus = {0,0};
 plus.x = one.x + two.x;
 plus.y = one.y + two.y;

 return (plus);
}


int main (void)
{
 A1 one= {2,3};
 A1 two= {4,5};
 A1 three = sum(one,two);
 return 0;
}


gcc assembley (snippet of sum function)

_Z3sum2A1S_:
    .loc 1 8 0
    pushl    %ebp
    movl    %esp, %ebp
    .loc 1 9 0
    movl    8(%ebp), %eax
    movl    $0, (%eax)
    movl    8(%ebp), %eax
    movl    $0, 4(%eax)
    .loc 1 10 0
    movl    12(%ebp), %edx
    movl    20(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, (%eax)
    .loc 1 11 0
    movl    16(%ebp), %edx
    movl    24(%ebp), %eax
    addl    %eax, %edx
    movl    8(%ebp), %eax
    movl    %edx, 4(%eax)
.LBE2:
    .loc 1 14 0
    movl    8(%ebp), %eax
    popl    %ebp
    ret    $4

clang assembly (snippet of sum function)
_Z3sum2A1S_:
   .loc    1 8 0
    pushl    %edi
    pushl    %esi
    leal    24(%esp), %eax
    leal    16(%esp), %ecx
    movl    12(%esp), %edx
    .loc    1 9 17 prologue_end
    movl    $0, 4(%edx)
    movl    $0, (%edx)
    .loc    1 10 2
    movl    (%ecx), %esi
    movl    (%eax), %edi
    addl    %edi, %esi
    movl    %esi, (%edx)
    .loc    1 11 2
    movl    4(%ecx), %ecx
    movl    4(%eax), %eax
    addl    %eax, %ecx
    movl    %ecx, 4(%edx)
    .loc    1 13 2
    popl    %esi
    popl    %edi
    ret    $4


But while returning int value clang returns with eax... as expect. Problem comes with when used struct/class

Is the behaviour of llvm as per the standards or is this a bug??









On Thu, Nov 29, 2012 at 12:40 PM, Mayur Pandey <[hidden email]<mailto:[hidden email]>> wrote:


For the given test:

class A1 {
  int x;
  int y;

  public:

  A1(int a, int b)
  {
   x=a;
   y=b;
  }

A1 operator+(const A1&);
};


A1 A1::operator+(const A1& second)
{
 A1 sum(0,0);
 sum.x = x + second.x;
 sum.y = y + second.y;

 return (sum);
}


int main (void)
{
 A1 one(2,3);
 A1 two(4,5);

 return 0;
}


when the exectable of this code is debugged in gdb for i386, we dont get the
expected results.

when we break at return 0; and give the command: print one + two, the result
should be $1 = {x = 6, y = 8}, but the result obtained is $1 = {x = 2, y = 3}.

This is related to debug information generated, as normally the overloading is
occuring.
eg: A1 three = one + two results {x = 6, y = 8}.


On checking the assembly, a suspicious entry is found which may be related for
the failure:

    #DEBUG_VALUE: operator+:this <- undef
    #DEBUG_VALUE: operator+:second <- undef


--
Thanx & Regards
Mayur Pandey








--
Thanx & Regards
Mayur Pandey









--
Thanx & Regards
Mayur Pandey
Senior Software Engineer
Samsung India Software Operations
Bangalore
+91-9742959541

 
 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Renato Golin-4
On 2 December 2012 08:12, Mayur Pandey <[hidden email]> wrote:
> So is this just a coincidence for g++ that eax points to this address and
> gdb prints the right value on the command print sum(one,two)??

The code is small, and the structure is probably set at the end of the
block, so I think it's not that much of a coincidence.

Regardless of the specific value on that specific compilation unit,
you should never rely on behaviour of clobbered registers. That
function returns void, you should look up in the caller, where is the
address of the structure.

Does the code execute correctly? Does a printf on the sum outputs the
correct value? StrucRet is stable on Intel for years, I'd be surprised
id that didn't work.

However, it's possible that clang is messing up the position of the
structure in Dwarf, so I'd investigate the Dwarf emission first, since
your problem seems to bee with clang+gdb.



--
cheers,
--renato

http://systemcall.org/
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Mayur Pandey
Hi,

I was going through this issue along with the standards. What the standard states is(reference: http://www.sco.com/developers/devspecs/abi386-4.pdf):

If a function returns a structure or union, then the caller provides space for the
return value and places its address on the stack as argument word zero. In effect,
this address becomes a ‘‘hidden’’ first argument. Having the caller supply the
return object’s space allows re-entrancy.

A function that returns a structure or union also sets% e a x to the value of the original
address of the caller’s area before it returns. Thus when the caller receives
control again, the address of the returned object resides in register% e a x and can
be used to access the object. Both the calling and the called functions must
cooperate to pass the return value successfully.

Also i verified that through the assembly code, that when the caller calls  the callee function, the hidden pointer is stored in eax(other arguments being passed in ecx and edx). But the callee function modifies eax and in the end it does not store the hidden pointer in eax, but it is stored in edx.

So this seems to be the cause of the problem.

@Renato Golin:- Does the code execute correctly? Does a printf on the sum outputs the
correct value? : yes the code executes correctly and some gives the correct value. Its only in gdb that we face this problem as gdb expects the hidden pointer in eax.

Note: GDB  "struct return convention" : The caller passes an additional hidden first parameter to the caller.  That parameter contains the address at which the value being returned should be stored. 


On Mon, Dec 3, 2012 at 2:37 PM, Renato Golin <[hidden email]> wrote:
On 2 December 2012 08:12, Mayur Pandey <[hidden email]> wrote:
> So is this just a coincidence for g++ that eax points to this address and
> gdb prints the right value on the command print sum(one,two)??

The code is small, and the structure is probably set at the end of the
block, so I think it's not that much of a coincidence.

Regardless of the specific value on that specific compilation unit,
you should never rely on behaviour of clobbered registers. That
function returns void, you should look up in the caller, where is the
address of the structure.

Does the code execute correctly? Does a printf on the sum outputs the
correct value? StrucRet is stable on Intel for years, I'd be surprised
id that didn't work.

However, it's possible that clang is messing up the position of the
structure in Dwarf, so I'd investigate the Dwarf emission first, since
your problem seems to bee with clang+gdb.



--
cheers,
--renato

http://systemcall.org/



--
Thanx & Regards
Mayur Pandey


 
 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Renato Golin-4
On 3 December 2012 10:42, Mayur Pandey <[hidden email]> wrote:
> So this seems to be the cause of the problem.

I guess you're mixing two different problems. First, is the possible
lack of conformance with the ABI you state, which I can't comment
since I don't know that ABI very well. Second, is the fact that clang
is not printing correct debug information (or is not interoperating
well enough with gdb).

Fixing the first issue will not necessarily fix the second.


> @Renato Golin:- Does the code execute correctly? Does a printf on the sum
> outputs the
> correct value? : yes the code executes correctly and some gives the correct
> value. Its only in gdb that we face this problem as gdb expects the hidden
> pointer in eax.

As I expected. Following the ABI is not a requirement to have working
code, or a debuggable code. GDB is probably expecting programs to
follow the ABI if they do not have decent Dwarf, which seems clang is
failing on both.

Debuggers have to deal with all sorts of user (and compiler) code, and
to give users the "debug illusion", they make too many guesses.
However, if the Dwarf information is correct to begin with, I
seriously hope that GDB would rely on that, rather than "expect"
values to be on specific registers.

Have a look in the Dwarf symbols clang generates with your code and
make sure that clang is not printing the correct location information
for that variable on the ranges where it lives on registers and which
registers.

If clang's info is right, there's only the ABI bug and GDB is being
silly. If the info is wrong, then we may need to fix *both* bugs (ABI
+ Dwarf), not just the ABI one.


--
cheers,
--renato

http://systemcall.org/
_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: operator overloading fails while debugging with gdb for i386

Mayur Pandey
Hi,

The issue seems in the file x86ISelLowering.cpp where we dont have an implementation for returning the hidden pointer in the specified register for 32 bit. We do have it for 64bit. On adding the following:

in function
X86TargetLowering::LowerReturn

 if (!(Subtarget->is64Bit()) &&
      DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
    MachineFunction &MF = DAG.getMachineFunction();
    X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
    unsigned Reg = FuncInfo->getSRetReturnReg();
    assert(Reg &&
           "SRetReturnReg should have been set in LowerFormalArguments().");
    SDValue Val = DAG.getCopyFromReg(Chain, dl, Reg, getPointerTy());

    Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Val, Flag);
    Flag = Chain.getValue(1);

    MRI.addLiveOut(X86::EAX);
  }

in function
X86TargetLowering::LowerFormalArguments

 if (!(Is64Bit) && MF.getFunction()->hasStructRetAttr()) {
    X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
    unsigned Reg = FuncInfo->getSRetReturnReg();
    if (!Reg) {
      Reg = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i32));
      FuncInfo->setSRetReturnReg(Reg);
    }
    SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), dl, Reg, InVals[0]);
    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Copy, Chain);
  }

we get the correct output in gdb and the there are no side-effects also.

Please verify whether this is a genuine fix.

The

On Mon, Dec 3, 2012 at 4:46 PM, Renato Golin <[hidden email]> wrote:
On 3 December 2012 10:42, Mayur Pandey <[hidden email]> wrote:
> So this seems to be the cause of the problem.

I guess you're mixing two different problems. First, is the possible
lack of conformance with the ABI you state, which I can't comment
since I don't know that ABI very well. Second, is the fact that clang
is not printing correct debug information (or is not interoperating
well enough with gdb).

Fixing the first issue will not necessarily fix the second.


> @Renato Golin:- Does the code execute correctly? Does a printf on the sum
> outputs the
> correct value? : yes the code executes correctly and some gives the correct
> value. Its only in gdb that we face this problem as gdb expects the hidden
> pointer in eax.

As I expected. Following the ABI is not a requirement to have working
code, or a debuggable code. GDB is probably expecting programs to
follow the ABI if they do not have decent Dwarf, which seems clang is
failing on both.

Debuggers have to deal with all sorts of user (and compiler) code, and
to give users the "debug illusion", they make too many guesses.
However, if the Dwarf information is correct to begin with, I
seriously hope that GDB would rely on that, rather than "expect"
values to be on specific registers.

Have a look in the Dwarf symbols clang generates with your code and
make sure that clang is not printing the correct location information
for that variable on the ranges where it lives on registers and which
registers.

If clang's info is right, there's only the ABI bug and GDB is being
silly. If the info is wrong, then we may need to fix *both* bugs (ABI
+ Dwarf), not just the ABI one.


--
cheers,
--renato

http://systemcall.org/



--
Thanx & Regards
Mayur Pandey
Senior Software Engineer
Samsung India Software Operations
Bangalore
+91-9742959541

 
 


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev