-
Notifications
You must be signed in to change notification settings - Fork 202
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent crash on ARM32 #1412
Prevent crash on ARM32 #1412
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -193,7 +193,7 @@ static int GetDwarfRegNum(Triple::ArchType ArchType, int RegNum) { | |
case RegNumArm::REGNUM_PC: return 15; | ||
// fp registers | ||
default: | ||
return RegNum - static_cast<int>(RegNumArm::REGNUM_COUNT) + 64; | ||
return (RegNum - static_cast<int>(RegNumArm::REGNUM_COUNT)) / 2 + 256; | ||
} | ||
case Triple::aarch64: // fall through | ||
case Triple::aarch64_be: | ||
|
@@ -284,6 +284,54 @@ static int GetDwarfFpRegNum(Triple::ArchType ArchType) | |
} | ||
} | ||
|
||
static int GetRegOpSize(int DwarfRegNum) { | ||
if (DwarfRegNum <= 31) { | ||
return 1; | ||
} | ||
else if (DwarfRegNum < 128) { | ||
return 2; | ||
} | ||
else if (DwarfRegNum < 16384) { | ||
return 3; | ||
} | ||
else { | ||
assert(false && "Too big register number"); | ||
return 0; | ||
} | ||
} | ||
|
||
static void EmitBreg(MCObjectStreamer* Streamer, int DwarfRegNum, StringRef bytes) { | ||
if (DwarfRegNum <= 31) { | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1); | ||
} | ||
else { | ||
Streamer->EmitIntValue(dwarf::DW_OP_bregx, 1); | ||
Streamer->EmitULEB128IntValue(DwarfRegNum); | ||
} | ||
Streamer->EmitBytes(bytes); | ||
} | ||
|
||
static void EmitBreg(MCObjectStreamer* Streamer, int DwarfRegNum, int value) { | ||
if (DwarfRegNum <= 31) { | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1); | ||
} | ||
else { | ||
Streamer->EmitIntValue(dwarf::DW_OP_bregx, 1); | ||
Streamer->EmitULEB128IntValue(DwarfRegNum); | ||
} | ||
Streamer->EmitSLEB128IntValue(value); | ||
} | ||
|
||
static void EmitReg(MCObjectStreamer* Streamer, int DwarfRegNum) { | ||
if (DwarfRegNum <= 31) { | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); | ||
} | ||
else { | ||
Streamer->EmitIntValue(dwarf::DW_OP_regx, 1); | ||
Streamer->EmitULEB128IntValue(DwarfRegNum); | ||
} | ||
} | ||
|
||
static void EmitVarLocation(MCObjectStreamer *Streamer, | ||
const ICorDebugInfo::NativeVarInfo &VarInfo, | ||
bool IsLocList = false) { | ||
|
@@ -307,22 +355,21 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
case ICorDebugInfo::VLT_REG: { | ||
DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlReg.vlrReg); | ||
if (IsByRef) { | ||
Len = 2; | ||
Len = 1 + GetRegOpSize(DwarfRegNum); | ||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
} else { | ||
Streamer->EmitULEB128IntValue(Len); | ||
} | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1); | ||
Streamer->EmitSLEB128IntValue(0); | ||
EmitBreg(Streamer, DwarfRegNum, 0); | ||
} else { | ||
Len = 1; | ||
Len = GetRegOpSize(DwarfRegNum); | ||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
} else { | ||
Streamer->EmitULEB128IntValue(Len); | ||
} | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); | ||
EmitReg(Streamer, DwarfRegNum); | ||
} | ||
|
||
break; | ||
|
@@ -331,6 +378,7 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
IsByRef = true; | ||
case ICorDebugInfo::VLT_STK2: | ||
IsStk2 = true; | ||
case ICorDebugInfo::VLT_FPSTK: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you actually hit this case? I would not expect it to be hit on. Floating point stack is a legacy 32-bit x86 that are not using anymore even on 32-bit x86. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is hit. I was tired of seeing assertion. This change was fishy to me too. But I do not know where to start looking. With that hint, I try to pin-point what can cause code to hit that location. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have looked around. |
||
case ICorDebugInfo::VLT_STK: { | ||
DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsStk2 ? VarInfo.loc.vlStk2.vls2BaseReg : | ||
VarInfo.loc.vlStk.vlsBaseReg); | ||
|
@@ -342,24 +390,22 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
StringRef OffsetRepr = OSE.str(); | ||
|
||
if (IsByRef) { | ||
Len = OffsetRepr.size() + 2; | ||
Len = OffsetRepr.size() + 1 + GetRegOpSize(DwarfBaseRegNum); | ||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
} else { | ||
Streamer->EmitULEB128IntValue(Len); | ||
} | ||
Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); | ||
Streamer->EmitBytes(OffsetRepr); | ||
EmitBreg(Streamer, DwarfBaseRegNum, OffsetRepr); | ||
Streamer->EmitIntValue(dwarf::DW_OP_deref, 1); | ||
} else { | ||
Len = OffsetRepr.size() + 1; | ||
Len = OffsetRepr.size() + GetRegOpSize(DwarfBaseRegNum); | ||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
} else { | ||
Streamer->EmitULEB128IntValue(Len); | ||
} | ||
Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); | ||
Streamer->EmitBytes(OffsetRepr); | ||
EmitBreg(Streamer, DwarfBaseRegNum, OffsetRepr); | ||
} | ||
|
||
break; | ||
|
@@ -368,18 +414,19 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg1); | ||
DwarfRegNum2 = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg2); | ||
|
||
Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) * 2; | ||
Len = (GetRegOpSize(DwarfRegNum2) /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) | ||
+ (GetRegOpSize(DwarfRegNum) /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */); | ||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
} else { | ||
Streamer->EmitULEB128IntValue(Len + 1); | ||
} | ||
|
||
Streamer->EmitIntValue(DwarfRegNum2 + dwarf::DW_OP_reg0, 1); | ||
EmitReg(Streamer, DwarfRegNum2); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
|
||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); | ||
EmitReg(Streamer, DwarfRegNum); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
|
||
|
@@ -399,8 +446,8 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
VarInfo.loc.vlStkReg.vlsrStk.vlsrsOffset, OSE); | ||
StringRef OffsetRepr = OSE.str(); | ||
|
||
Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) + | ||
(1 /*DW_OP_breg */ + OffsetRepr.size() + 1 /* DW_OP_piece */ + 1 /* Reg size */); | ||
Len = (GetRegOpSize(DwarfRegNum) /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) + | ||
(GetRegOpSize(DwarfBaseRegNum) /*DW_OP_breg */ + OffsetRepr.size() + 1 /* DW_OP_piece */ + 1 /* Reg size */); | ||
|
||
if (IsLocList) { | ||
Streamer->EmitIntValue(Len, 2); | ||
|
@@ -409,28 +456,25 @@ static void EmitVarLocation(MCObjectStreamer *Streamer, | |
} | ||
|
||
if (IsRegStk) { | ||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); | ||
EmitReg(Streamer, DwarfRegNum); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
|
||
Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); | ||
Streamer->EmitBytes(OffsetRepr); | ||
EmitBreg(Streamer, DwarfBaseRegNum, OffsetRepr); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
} else { | ||
Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1); | ||
Streamer->EmitBytes(OffsetRepr); | ||
EmitBreg(Streamer, DwarfBaseRegNum, OffsetRepr); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
|
||
Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1); | ||
EmitReg(Streamer, DwarfRegNum); | ||
Streamer->EmitIntValue(dwarf::DW_OP_piece, 1); | ||
Streamer->EmitULEB128IntValue(TargetPointerSize); | ||
} | ||
|
||
break; | ||
} | ||
case ICorDebugInfo::VLT_FPSTK: | ||
case ICorDebugInfo::VLT_FIXED_VA: | ||
assert(false && "Unsupported varloc type!"); | ||
default: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the dwarf manual: "The DW_OP_bregx operation has two operands: a register which is specified by an unsigned LEB128 number, followed by a signed LEB128 offset.". It would be nice to emit the offset as part of this function instead of emitting it in the calling code.