Merge pull request #6979 from rainers/issue15432

fix issue 15432: Win64: bad code offset in debug line number info
merged-on-behalf-of: Rainer Schuetze <rainers@users.noreply.github.com>
This commit is contained in:
The Dlang Bot 2017-07-26 08:57:16 +02:00 committed by GitHub
commit a7867ca72b
2 changed files with 114 additions and 3 deletions

View file

@ -5384,7 +5384,7 @@ void pinholeopt(code *c,block *b)
}
/* Look for LEA reg,[ireg], replace with MOV reg,ireg */
else if (op == LEA)
if (op == LEA)
{ rm = c->Irm & 7;
mod = c->Irm & modregrm(3,0,0);
if (mod == 0)

View file

@ -1,4 +1,6 @@
// REQUIRED_ARGS: -gf
// PERMUTE_ARGS:
import core.time;
void main(string[] args)
@ -21,7 +23,7 @@ void main(string[] args)
}
// dumpSymbols(globals, SymTagEnum.SymTagNull, null, 0);
IDiaSymbol objsym = searchSymbol(globals, "object.Object");
testSymbolHasChildren(objsym, "object.Object");
objsym.Release();
@ -34,12 +36,25 @@ void main(string[] args)
testSymbolHasChildren(ctsym, "core.time.ClockType");
ctsym.Release();
testLineNumbers(session, globals);
source.Release();
session.Release();
globals.Release();
}
}
///////////////////////////////////////////////////////////////
// https://issues.dlang.org/show_bug.cgi?id=15432
void call15432(string col) {}
int test15432() // line 8
{
call15432(null);
return 0;
}
enum lineAfterTest15432 = __LINE__;
version(CRuntime_Microsoft):
void testSymbolHasChildren(IDiaSymbol sym, string name)
@ -56,6 +71,21 @@ void testSymbolHasChildren(IDiaSymbol sym, string name)
enumSymbols.Release();
}
void testLineNumbers(IDiaSession session, IDiaSymbol globals)
{
IDiaSymbol funcsym = searchSymbol(globals, test15432.mangleof);
assert(funcsym, "symbol test15432 not found");
ubyte[] funcRange;
Line[] lines = findSymbolLineNumbers(session, funcsym, &funcRange);
assert(lines, "no line number info for test15432");
//dumpLineNumbers(lines, funcRange);
assert (lines[$-1].line == lineAfterTest15432 - 1);
ubyte codeByte = lines[$-1].addr[0];
assert(codeByte == 0x48 || codeByte == 0x5d || codeByte == 0xc3); // should be one of "mov rsp,rbp", "pop rbp" or "ret"
}
import core.stdc.stdio;
import core.stdc.wchar_;
@ -470,6 +500,13 @@ interface IDiaEnumSymbolsByAddr : IUnknown
interface IDiaEnumLineNumbers : IUnknown
{
HRESULT get__NewEnum(IUnknown *pRetVal);
HRESULT get_Count(LONG *pRetVal);
HRESULT Item(DWORD index, IDiaLineNumber *lineNumber);
HRESULT Next(ULONG celt, IDiaLineNumber *rgelt, ULONG *pceltFetched);
HRESULT Skip(ULONG celt);
HRESULT Reset();
HRESULT Clone(IDiaEnumLineNumbers *ppenum);
}
interface IDiaSourceFile : IUnknown
@ -478,6 +515,20 @@ interface IDiaSourceFile : IUnknown
interface IDiaLineNumber : IUnknown
{
HRESULT get_compiland(IDiaSymbol *pRetVal);
HRESULT get_sourceFile(IDiaSourceFile *pRetVal);
HRESULT get_lineNumber(DWORD *pRetVal);
HRESULT get_lineNumberEnd(DWORD *pRetVal);
HRESULT get_columnNumber(DWORD *pRetVal);
HRESULT get_columnNumberEnd(DWORD *pRetVal);
HRESULT get_addressSection(DWORD *pRetVal);
HRESULT get_addressOffset(DWORD *pRetVal);
HRESULT get_relativeVirtualAddress(DWORD *pRetVal);
HRESULT get_virtualAddress(ULONGLONG *pRetVal);
HRESULT get_length(DWORD *pRetVal);
HRESULT get_sourceFileId(DWORD *pRetVal);
HRESULT get_statement(BOOL *pRetVal);
HRESULT get_compilandId(DWORD *pRetVal);
}
interface IDiaEnumSourceFiles : IUnknown
@ -650,7 +701,7 @@ bool openDebugInfo(IDiaDataSource* source, IDiaSession* session, IDiaSymbol* glo
// Retrieve a reference to the global scope
hr = session.get_globalScope(globals);
hr == S_OK || assert(false, "get_globalScope failed");
return true;
}
@ -712,3 +763,63 @@ IDiaSymbol searchSymbol(IDiaSymbol parent, const(wchar)* name, SymTagEnum tag =
enumSymbols.Release();
return sym;
}
struct Line
{
DWORD line;
ubyte* addr;
}
// linker generated symbol
__gshared extern(C) extern ubyte __ImageBase;
Line[] findSymbolLineNumbers(IDiaSession session, IDiaSymbol sym, ubyte[]* funcRange)
{
DWORD rva;
HRESULT hr = sym.get_relativeVirtualAddress(&rva);
if (hr != S_OK)
return null;
ULONGLONG length;
hr = sym.get_length(&length);
if (hr != S_OK)
return null;
IDiaEnumLineNumbers dialines;
hr = session.findLinesByRVA(rva, cast(DWORD)length, &dialines);
if (hr != S_OK)
return null;
scope(exit) dialines.Release();
ubyte* rvabase = &__ImageBase;
*funcRange = rvabase[rva .. rva+length];
Line[] lines;
IDiaLineNumber line;
ULONG fetched;
while(dialines.Next(1, &line, &fetched) == S_OK)
{
DWORD lno, lrva;
if (line.get_lineNumber(&lno) == S_OK && line.get_relativeVirtualAddress(&lrva) == S_OK)
lines ~= Line(lno, rvabase + lrva);
line.Release();
}
return lines;
}
void dumpLineNumbers(Line[] lines, ubyte[] funcRange)
{
import core.stdc.stdio;
void dumpLine(int lno, ubyte* beg, ubyte* end)
{
printf("%8d:", lno);
while (beg < end)
printf(" %02x", *beg++);
printf("\n");
}
if (lines[0].addr != funcRange.ptr)
dumpLine(0, funcRange.ptr, lines[0].addr);
for (int i = 1; i < lines.length; i++)
dumpLine(lines[i-1].line, lines[i-1].addr, lines[i].addr);
dumpLine(lines[$-1].line, lines[$-1].addr, funcRange.ptr + funcRange.length);
}