Skip to content

Commit 5cfd92e

Browse files
authored
final IL2CPP symbolication changes (#920)
1 parent e23984d commit 5cfd92e

File tree

13 files changed

+126
-63
lines changed

13 files changed

+126
-63
lines changed

.buildkite/pipeline.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ steps:
1212
UNITY_VERSION: *2021
1313
commands:
1414
- rake code:verify
15+
retry:
16+
automatic:
17+
- exit_status: "*"
18+
limit: 1
1519

1620
- label: Run Unit Tests
1721
timeout_in_minutes: 5

.buildkite/unity.2020.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ steps:
2323
- features/fixtures/build_android_apk.log
2424
command:
2525
- "bundle install"
26-
- "bundle exec maze-runner --os macos features/build/build_android.feature"
26+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_android.feature"
2727
retry:
2828
automatic:
2929
- exit_status: "*"
@@ -49,7 +49,7 @@ steps:
4949
- features/fixtures/unity.log
5050
command:
5151
- "bundle install"
52-
- "bundle exec maze-runner --os macos features/build/build_ios.feature"
52+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_ios.feature"
5353
retry:
5454
automatic:
5555
- exit_status: "*"

.buildkite/unity.2021.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ steps:
2121
- features/fixtures/build_android_apk.log
2222
command:
2323
- "bundle install"
24-
- "bundle exec maze-runner --os macos features/build/build_android.feature"
24+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_android.feature"
2525
retry:
2626
automatic:
2727
- exit_status: "*"
@@ -39,10 +39,11 @@ steps:
3939
- Bugsnag.unitypackage
4040
upload:
4141
- features/fixtures/maze_runner/mazerunner_2021.ipa
42+
- features/fixtures/maze_runner/build.xcresult
4243
- features/fixtures/unity.log
4344
command:
4445
- "bundle install"
45-
- "bundle exec maze-runner --os macos features/build/build_ios.feature"
46+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_ios.feature"
4647
retry:
4748
automatic:
4849
- exit_status: "*"

.buildkite/unity.2022.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ steps:
2323
- features/fixtures/build_android_apk.log
2424
command:
2525
- "bundle install"
26-
- "bundle exec maze-runner --os macos features/build/build_android.feature"
26+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_android.feature"
2727
retry:
2828
automatic:
2929
- exit_status: "*"
@@ -44,7 +44,7 @@ steps:
4444
- features/fixtures/unity.log
4545
command:
4646
- "bundle install"
47-
- "bundle exec maze-runner --os macos features/build/build_ios.feature"
47+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_ios.feature"
4848
retry:
4949
automatic:
5050
- exit_status: "*"

.buildkite/unity.6000.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ steps:
2323
- features/fixtures/build_android_apk.log
2424
command:
2525
- "bundle install"
26-
- "bundle exec maze-runner --os macos features/build/build_android.feature"
26+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_android.feature"
2727
retry:
2828
automatic:
2929
- exit_status: "*"
@@ -44,7 +44,7 @@ steps:
4444
- features/fixtures/unity.log
4545
command:
4646
- "bundle install"
47-
- "bundle exec maze-runner --os macos features/build/build_ios.feature"
47+
- "bundle exec maze-runner --os=macos --port=$((MAZE_RUNNER_PORT)) features/build/build_ios.feature"
4848
retry:
4949
automatic:
5050
- exit_status: "*"

Bugsnag/Assets/Bugsnag/Editor/SymbolUpload/BugsnagCLI.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace BugsnagUnity.Editor
88
{
99
internal class BugsnagCLI
1010
{
11-
private const string DOWNLOADED_CLI_VERSION = "2.9.1";
11+
private const string DOWNLOADED_CLI_VERSION = "3.3.1";
1212
private readonly string DOWNLOADED_CLI_PATH = Path.Combine(Application.dataPath, "../bugsnag/bin/bugsnag_cli");
1313
private readonly string DOWNLOADED_CLI_URL = $"https://github.com/bugsnag/bugsnag-cli/releases/download/v{DOWNLOADED_CLI_VERSION}/";
1414
private readonly string _cliExecutablePath;
@@ -50,6 +50,9 @@ public void UploadAndroidSymbols(string buildOutputPath, string apiKey, string v
5050
{
5151
args += $" --application-id={bundleId}";
5252
}
53+
#if !UNITY_2021_1_OR_NEWER
54+
args += " --no-upload-il2cpp-mapping";
55+
#endif
5356
int exitCode = StartProcess(_cliExecutablePath, args, out string output, out string error);
5457

5558
if (exitCode != 0)
@@ -193,7 +196,10 @@ private int StartProcess(string fileName, string arguments, out string standardO
193196

194197
public string GetIosDsymUploadCommand(string apiKey, string uploadEndpoint)
195198
{
196-
var command = $"{_cliExecutablePath} upload xcode-build --api-key={apiKey} $DWARF_DSYM_FOLDER_PATH";
199+
var command = $"{_cliExecutablePath} upload unity-ios --api-key={apiKey} --dsym-path=$DWARF_DSYM_FOLDER_PATH --project-root={Application.dataPath} {Application.dataPath.Replace("/Assets", string.Empty)}";
200+
#if !UNITY_2021_1_OR_NEWER
201+
command += " --no-upload-il2cpp-mapping";
202+
#endif
197203
if (!string.IsNullOrEmpty(uploadEndpoint))
198204
{
199205
command += $" --upload-api-root-url={uploadEndpoint}";

Bugsnag/Assets/Bugsnag/Runtime/Native/Cocoa/LoadedImages.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,26 @@ public void Refresh(String? mainImageFileName)
4545

4646
UInt64 mainLoadAddress = 0;
4747
var images = new LoadedImage[count];
48+
4849
for (UInt64 i = 0; i < count; i++)
4950
{
5051
var nativeImage = nativeImages[i];
51-
var uuid = new byte[16];
52-
Marshal.Copy(nativeImage.UuidBytes, uuid, 0, 16);
53-
var fileName = Marshal.PtrToStringAnsi(nativeImage.FileName);
52+
53+
var uuidBytes = new byte[16];
54+
Marshal.Copy(nativeImage.UuidBytes, uuidBytes, 0, 16);
55+
56+
var fileName = Marshal.PtrToStringAnsi(nativeImage.FileName);
5457
var isMainImage = fileName == mainImageFileName;
5558

59+
// Build canonical RFC-4122 text directly from the 16 bytes (no swapping)
60+
string uuidText = UuidTextFromBigEndianBytes(uuidBytes);
61+
5662
var image = new LoadedImage(nativeImage.LoadAddress,
5763
nativeImage.Size,
5864
fileName,
59-
new Guid(uuid).ToString(),
65+
uuidText,
6066
isMainImage);
67+
6168
if (isMainImage)
6269
{
6370
mainLoadAddress = image.LoadAddress;
@@ -122,6 +129,26 @@ int IComparer.Compare(Object x, Object y)
122129
return 0;
123130
}
124131
}
132+
133+
private static string UuidTextFromBigEndianBytes(byte[] b)
134+
{
135+
if (b == null || b.Length != 16) throw new ArgumentException(nameof(b));
136+
137+
char[] chars = new char[36];
138+
int j = 0;
139+
for (int i = 0; i < 16; i++)
140+
{
141+
if (i == 4 || i == 6 || i == 8 || i == 10)
142+
chars[j++] = '-';
143+
144+
byte v = b[i];
145+
int hi = v >> 4, lo = v & 0xF;
146+
chars[j++] = (char)(hi < 10 ? '0' + hi : 'A' + (hi - 10));
147+
chars[j++] = (char)(lo < 10 ? '0' + lo : 'A' + (lo - 10));
148+
}
149+
return new string(chars);
150+
}
151+
125152
}
126153
}
127154
#endif

Bugsnag/Assets/Bugsnag/Runtime/Native/Cocoa/NativeClient.cs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -509,46 +509,50 @@ private StackTraceLine[] ToStackFrames(System.Exception exception, IntPtr[] nati
509509
var address = (UInt64)nativeAddresses[i].ToInt64();
510510
var image = loadedImages.FindImageAtAddress(address);
511511

512-
var trace = new StackTraceLine();
513-
trace.FrameAddress = string.Format("0x{0:X}", address);
514-
trace.Method = method.ToString();
512+
var frame = new StackTraceLine();
513+
frame.FrameAddress = string.Format("0x{0:X}", address);
514+
frame.Method = method.ToString();
515+
frame.Type = "cocoa";
515516
if (image != null)
516517
{
517518
if (address < image.LoadAddress)
518519
{
519520
// It's a relative address
520-
trace.FrameAddress = string.Format("0x{0:X}", address + image.LoadAddress);
521+
frame.FrameAddress = string.Format("0x{0:X}", address + image.LoadAddress);
521522
}
522-
trace.MachoFile = image.FileName;
523-
trace.MachoLoadAddress = string.Format("0x{0:X}", image.LoadAddress);
524-
trace.MachoUuid = image.Uuid;
525-
trace.InProject = image.IsMainImage;
523+
frame.MachoFile = image.FileName;
524+
frame.MachoLoadAddress = string.Format("0x{0:X}", image.LoadAddress);
525+
frame.MachoUuid = FormatImageUuid(image.Uuid);
526+
frame.InProject = image.IsMainImage;
526527
}
527528
else
528529
{
529-
trace.MachoFile = safeMainImageFileName;
530-
trace.MachoLoadAddress = "0x0";
531-
trace.MachoUuid = mainImageFormattedUuid;
532-
trace.InProject = true;
530+
frame.MachoFile = safeMainImageFileName;
531+
frame.MachoLoadAddress = "0x0";
532+
frame.MachoUuid = mainImageFormattedUuid;
533+
frame.InProject = true;
533534
}
534-
stackFrames[i] = trace;
535+
stackFrames[i] = frame;
535536
}
536537
return stackFrames;
537538
}
538539

539-
private string FormatImageUuid(string imageUuid)
540+
private static string FormatImageUuid(string uuid)
540541
{
541-
if (imageUuid == null || imageUuid.Length != 32)
542-
{
543-
return null;
544-
}
542+
if (string.IsNullOrEmpty(uuid)) return uuid;
545543

546-
byte[] mainImageUuidBytes = new byte[16];
547-
for (int i = 0; i < 16; i++)
544+
string hex = uuid.Replace("-", "").Trim();
545+
if (hex.Length != 32) return uuid; // leave unexpected formats alone
546+
547+
for (int i = 0; i < 32; i++)
548548
{
549-
mainImageUuidBytes[i] = Convert.ToByte(imageUuid.Substring(i * 2, 2), 16);
549+
char c = hex[i];
550+
bool ok = (c >= '0' && c <= '9') || (c | 0x20) >= 'a' && (c | 0x20) <= 'f';
551+
if (!ok) return uuid;
550552
}
551-
return new Guid(mainImageUuidBytes).ToString();
553+
554+
hex = hex.ToUpperInvariant();
555+
return $"{hex.Substring(0,8)}-{hex.Substring(8,4)}-{hex.Substring(12,4)}-{hex.Substring(16,4)}-{hex.Substring(20)}";
552556
}
553557

554558
public StackTraceLine[] ToStackFrames(System.Exception exception)

Bugsnag/Assets/Bugsnag/Runtime/Payload/Error.cs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using System.Linq;
55
using System.Reflection;
66
using System.Text.RegularExpressions;
7-
7+
using UnityEngine;
88
namespace BugsnagUnity.Payload
99
{
1010
/// <summary>
@@ -16,16 +16,6 @@ public class Error : Dictionary<string, object>, IError
1616

1717
internal bool IsAndroidJavaException;
1818

19-
private const string COMPILATION_PLATFORM =
20-
#if ENABLE_IL2CPP
21-
"il2cpp"
22-
#elif ENABLE_MONO
23-
"mono"
24-
#else
25-
"unknown"
26-
#endif
27-
;
28-
2919
private const string ANDROID_JAVA_EXCEPTION_CLASS = "AndroidJavaException";
3020
private const string ERROR_CLASS_MESSAGE_PATTERN = @"^(?<errorClass>\S+):\s+(?<message>.*)";
3121
private const string NATIVE_ANDROID_ERROR_CLASS = "java.lang.Error";
@@ -36,6 +26,8 @@ public class Error : Dictionary<string, object>, IError
3626
private const string STACKTRACE_KEY = "stacktrace";
3727
private const string ERROR_TYPE_KEY = "type";
3828

29+
private static string _cachedErrorType;
30+
3931
internal Error(Dictionary<string, object> data)
4032
{
4133
foreach (var item in data)
@@ -68,7 +60,7 @@ internal Error(string errorClass, string message, IStackframe[] stackTrace, Hand
6860
_stacktrace = stackTrace.ToList();
6961
HandledState = handledState;
7062
IsAndroidJavaException = isAndroidJavaException;
71-
Type = COMPILATION_PLATFORM;
63+
Type = GetErrorType();
7264
}
7365

7466

@@ -140,5 +132,29 @@ public static bool ShouldSend(UnityLogMessage logMessage)
140132
match = Regex.Match(logMessage.StackTrace, NATIVE_ANDROID_MESSAGE_PATTERN, RegexOptions.Singleline);
141133
return !match.Success;
142134
}
135+
136+
private static string GetErrorType()
137+
{
138+
if (_cachedErrorType != null)
139+
{
140+
return _cachedErrorType;
141+
}
142+
143+
#if ENABLE_IL2CPP
144+
switch (Application.platform)
145+
{
146+
case RuntimePlatform.IPhonePlayer:
147+
_cachedErrorType = "cocoa";
148+
break;
149+
case RuntimePlatform.Android:
150+
_cachedErrorType = "c";
151+
break;
152+
default:
153+
_cachedErrorType = null;
154+
break;
155+
}
156+
#endif
157+
return _cachedErrorType;
158+
}
143159
}
144160
}

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
### Enhancements
4+
5+
- Enable IL2CPP line number symbolication fo riOS and Android via the BugSnag CLI [#920](https://github.com/bugsnag/bugsnag-unity/pull/920)
6+
37
## 8.6.2 (2025-07-16)
48

59
### Enhancements

0 commit comments

Comments
 (0)