This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Broken .loc directive in GAS


Hi all,
while investigating a GDB testsuite failure I found out that .debug_line section can sometimes be broken.


Take the example code temp.cc and compile it to temp.o:
$ g++ -g -c temp.cc

Inspecting .debug_line with 'readelf -wl temp.o' shows this:
[...]
 Line Number Statements:
  Extended opcode 2: set Address to 0x0
  Special opcode 13: advance Address by 0 to 0x0 and Line by 8 to 9
  Advance PC by 14 to e
  Extended opcode 1: End of Sequence

  Extended opcode 2: set Address to 0x0
  Special opcode 13: advance Address by 0 to 0x0 and Line by 8 to 9
  Advance PC by 14 to e
  Extended opcode 1: End of Sequence

  Extended opcode 2: set Address to 0x0
  Advance Line by 16 to 17
  Copy
  Special opcode 62: advance Address by 4 to 0x4 and Line by 1 to 18
  Special opcode 76: advance Address by 5 to 0x9 and Line by 1 to 19
  Advance Line by -6 to 13
  Special opcode 47: advance Address by 3 to 0xc and Line by 0 to 13
  Special opcode 201: advance Address by 14 to 0x1a and Line by 0 to 13
  Advance PC by constant 17 to 0x2b
  Special opcode 215: advance Address by 15 to 0x3a and Line by 0 to 13
  Special opcode 61: advance Address by 4 to 0x3e and Line by 0 to 13
  Advance PC by 20 to 52
  Extended opcode 1: End of Sequence
[...]

First two sequences are for constructors' sections and the third is for
the .text section.

What I don't understand are the last two lines in .text section, i.e.
  Advance PC by 20 to 52
  Extended opcode 1: End of Sequence

How does the GAS know it should advance the PC by 20? It probably
ment something like "Advance PC to the end of the section". Offset
0x52 points 2 bytes beyond the end of the section which triggers
problems when the file is linked:

$ g++ -o temp temp.o
$ readelf -wl temp

Then the .debug_line section (relevant part) is like this:
[...]
  Extended opcode 2: set Address to 0x400546
  [...]
  Extended opcode 1: End of Sequence

  Extended opcode 2: set Address to 0x400538
  Special opcode 13: advance Address by 0 to 0x400538 and Line by 8 to 9
  Advance PC by 14 to 400546
  Extended opcode 1: End of Sequence

  Extended opcode 2: set Address to 0x4004e8
  [...]
  Special opcode 61: advance Address by 4 to 0x400526 and Line by 0 to 13
  Advance PC by 20 to 40053a
  Extended opcode 1: End of Sequence
[...]

As you can see - second sequence starts at 0x400538 but third sequence
ends at 40053a, i.e. they overlap by two bytes. This confuses GDB
because it sorts the line numbers by their PC and overlapping sequences
don't make sense.

Everything written so far was seen on AMD64. However you can observe
exactly the same problem (off-by-2) on i386 as well.
The only difference is that i386 GCC puts another .loc mark right after
the function prologue, which is 3 bytes long, which eliminates the GDB
problem. This is not a correct solution however.

I suspect something is broken in the GAS - does anyone know these line
numbering internals?

I'm using gcc-3.3 and recent a snapshot of binutils (2.14.90 20030710) but the version from January gives the same output.

Thans in advance for any hint!

Michal Ludvig
--
* SuSE CR, s.r.o     * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
template<class T>
class T5 {
public:
    T5(int);
};

template<class T>
T5<T>::T5(int val)
{
}


T5<int> t5i(2);
template class T5<int>;

int main()
{
  return 0;  
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]