Skip to content
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

Fix tagged date on old *OS #477

Merged
merged 12 commits into from
May 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,6 @@
<Test
Identifier = "KSObjC_Tests/testCopyArrayContentsMutable">
</Test>
<Test
Identifier = "KSObjC_Tests/testDateDescription">
</Test>
<Test
Identifier = "KSObjC_Tests/testDateIsValid">
</Test>
<Test
Identifier = "KSObjC_Tests/testGetDateContents">
</Test>
</SkippedTests>
</TestableReference>
<TestableReference
Expand Down
81 changes: 45 additions & 36 deletions Sources/KSCrashRecordingCore/KSObjC.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,43 +398,52 @@ static uint64_t decodeExponent(uint64_t exp)
*/
static CFAbsoluteTime extractTaggedNSDate(const void* const object)
{
#pragma pack(4)
union {
uintptr_t raw;
struct {
uint64_t fraction : 52;
uint64_t exponent : 7;
uint64_t sign : 1;
uint64_t unused : 4;
} bits;
} encodedBits = { .raw = getTaggedPayload(object) };

if (encodedBits.raw == 0)
{
return 0.0;
}
if (encodedBits.raw == UINT64_MAX)
{
return -0.0;
}

#pragma pack(4)
union {
CFAbsoluteTime value;
struct {
uint64_t fraction : 52;
uint64_t exponent : 11;
uint64_t sign : 1;
} bits;
} decodedBits = {
.bits = {
.fraction = encodedBits.bits.fraction,
.exponent = decodeExponent(encodedBits.bits.exponent),
.sign = encodedBits.bits.sign
}
};
uintptr_t payload = getTaggedPayload(object);

if (kCFCoreFoundationVersionNumber > 1600) // https://github.com/apple/llvm-project/blob/5dc9d563e5a6cd2cdd44117697dead98955ccddf/lldb/source/Plugins/Language/ObjC/Cocoa.cpp#L1041
{
union {
uintptr_t raw;
struct {
uint64_t fraction : 52;
uint64_t exponent : 7;
uint64_t sign : 1;
uint64_t unused : 4;
} bits;
} encodedBits = { .raw = payload };

if (encodedBits.raw == 0)
return 0.0;
if (encodedBits.raw == UINT64_MAX)
return -0.0;

union {
CFAbsoluteTime value;
struct {
uint64_t fraction : 52;
uint64_t exponent : 11;
uint64_t sign : 1;
} bits;
} decodedBits = {
.bits = {
.fraction = encodedBits.bits.fraction,
.exponent = decodeExponent(encodedBits.bits.exponent),
.sign = encodedBits.bits.sign
}
};

return decodedBits.value;
return decodedBits.value;
}
else
{
// Payload is a 60-bit float. Fortunately we can just cast across from
// an integer pointer after shifting out the upper 4 bits.
union {
CFAbsoluteTime value;
uintptr_t raw;
} payloadBits = { .raw = payload << 4 };
return payloadBits.value;
}
}
#endif
/** Get any special class metadata we have about the specified class.
Expand Down
Loading