Understanding Objective-C throw call stack - objective-c

A user has just submitted a bug report to me, saying that my app crashed. The user also attached a throw call stack.
The part which seems to have caused the problem is:
3 My App 0x000000010d005483 My App + 17539
Is there a way to translate that address and/or the + 17539 to a line number in my code?
Keep in mind, I wasn't able to reproduce the bug on my machine, so I can't just build it in debug mode.

Check out this Tech note from Apple.
... This trace is similar to what you would see when stopping execution in the debugger, except that you are not given the method or function names, known as symbols. Instead, you have hexadecimal addresses and executable code - your application or system frameworks - to which they refer. You need to map these addresses to symbols. Unlike crash logs from Mac OS X, iPhone OS logs do not contain symbol information when they're written out. You have to symbolicate iPhone OS logs before you can analyze them.

I've been using GDB to do manual symbolication. It'd be too cumbersome if you were doing it a lot, but the typical crash log doesn't have very many symbols, and I only need to symbolicate a crash log once in a while.
The procedure is as follows:
Put the .dSYM file for your app in the same folder as the .app.*
Open Terminal and cd to the folder from step 1.
Start your app up in GDB:
$ gdb YourApp.app/Contents/MacOS/YourApp
Set the print asm-demangle and print symbol-file options:
set print asm-demangle on
set print symbol-filename on
Use the p/a command to find the line numbers for each address in your stack trace:
p/a 0x000000010d005483
These instructions are from this page (apparently no longer online).
*Note that the .dSYM has a UDID tying it to the particular build it was created with. So, if you don't have the original .dSYM file, you're in trouble. Theoretically, you can't even just pull the same revision from source control and rebuild because this UDID will be different.

Related

How do I access logs from the past day with os_log from Apple Watch?

I'm trying to troubleshoot an issue on watchOS.
I'm not sure how to reproduce the problem I'm seeing, but I do encounter it occasionally during testing on a real device in the wild, so I'm trying to use os_log in order to diagnose the problem after the fact.
As a first step, to make sure I understand how how to write to the log and access it later, I've attempted to log an event any time the app first loads.
In the ExtensionDelegate.swift file for my app, I added this:
import os.log
extension OSLog {
private static var subsystem = Bundle.main.bundleIdentifier!
static let health = OSLog(subsystem: subsystem,
category: "health")
}
Then, I updated the applicationDidBecomeActive delegate function with this:
func applicationDidBecomeActive() {
os_log("App Started",
log: OSLog.health,
type: .error)
}
I know it's not really an error message, but from what I've read, messages that are not .error are not written to saved to the log for later. I want to make sure it gets written to the log like a real error would.
I installed the sysdiagnose profile, then installed the the most recent version of my app.
After testing the app for the day, I attempted to export the file. Following the instructions I've found elsewhere, I produced a sysdiagnose on Apple Watch by holding the Digital Crown and Side button for two seconds (and felt the haptic feedback when I released).
Then, I put the watch on the charger for a few minutes per the instructions here, which recommended 15 minutes.
I opened the Watch app on my paired iPhone, then went to General > Diagnostic Logs and downloaded the sysdiagnose from Apple Watch, and sent it to my computer with AirDrop.
This gave me a tarball file (for example, sysdiagnose_2021.03.05_17-01-57-0700_Watch-OS_Watch_18S801.tar.gz). Once I decompressed that, I had a folder of lots of files and subfolders.
After poking around in this folder, I figured my best bet was to look in the system_logs.logarchive file. I opened that in the macOS Console app, set the Showing dropdown to All Messages, and looked around the time I opened the app. I didn't see any log output from my app.
I also filtered for "App Started" (the log message from my app) and didn't find anything.
Then, I filtered by category for "health" and didn't find the event I had logged.
Is system_logs.logarchive the correct place to be looking for the log output from my app?
If not, where should I be looking? Or what am I doing wrong?
I really want a better understanding of how I can log messages on Apple Watch so I can view them later so I can make my Apple Watch apps more robust, but I'm at a dead end.
Am I looking in the wrong place? Or am I setting up the logging wrong? Or is it something else? I would appreciate any guidance about this!
According to the Apple Dev Forms, sysdiagnose allows you to view the logs on your apple watch.

How to find my own functions in a ClojureScript error message?

I am a new ClojureScript user and I'm writing an application using Re-frame. When I get an error message (from ClojureScript), in most cases, I get a call stack ending in JavaScript code from a library. That is expected, but I don't get a function from my own code in the stack! Sometimes, I don't get any ClojureScript function calls at all, just JavaScript's. Is there a way to see the top of the stack in these error messages? Or to see the last function from my code/namespace in the stack?
That could be a huge help to me. Even small mistakes (such as, swapping operator's positions in a map call) are very hard to track. I should be doing something wrong.
It is said that ClojureScript error messages are an acquired taste. Because of the way the compiler works error messages can be cryptic.
What can help make ClojureScript error messages more readable is installing cljs-devtools or the fork Dirac. This has among other things:
The :hints feature.
The :hints feature is an attempt to augment uncaught exceptions and error object to include a bit of additional knowledge related to such errors. It tries to fetch the original source file, extract relevant part to show you more context and mark the javascript error there. This is expected to work only with :optimizations none compiler mode and it is disabled by default because it relies on monkey patching.
Better display of ClojureScript function names.
Example of nicer stack trace (from Dirac, but cljs-webtools already improves it a lot)
Installation
Enable custom formatters
Open DevTools with CMD-ALT-J
Go to Settings with F1 or by pressing the three dots
Check "Enable custom formatters" under Console
cljs-webtools
(See Installation):
Add configuration to the compiler in project.clj
{:builds
[{:id "dev"
:source-paths ["src/cljs"]
:figwheel {:on-jsload "blabla.core/reload"}
:compiler {(...)
:preloads [devtools.preload]
:external-config {:devtools/config {:features-to-install :all}}}}
Dirac
Install the Dirac Chrome extension.
Run Chrome with remote debugging enabled.
/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary \
--remote-debugging-port=9222 \
--no-first-run \
--user-data-dir=$A_PATH_TO_YOUR_USER_PROFILE_DIRECTORY
Add binaryage/dirac to dependencies in your project.clj
:dependencies [[binaryage/dirac "RELEASE"]]
(or use another one of the installation instructions).
If you use the re-frame Leiningen template the cljs-devtools are included by default

Data Formatters temporarily Unavailable, will re-try after a continue

I am working on Objective C to develop an app in I Pad. When I run the program its getting executed in Simulator of IPad. When I do the same connecting the device then I am facing an Error as GDB:Data Formatters temporarily unavailable,will re-try after a 'continue'.
Someone guide how to solve this issue.
Regards,
Vani.
This can be because of several reasons:
Memory issue. Try running your app with instruments to check
When it is unable to find a linked in shared library at launch time.
Also you can try running in a different target xcode and check if that works
Check all you breakpoints. In the Debugger window, click on "Show Breakpoints" and see if there are any unusually placed breakpoints
I also got the same problem in cocoa application.
Take a look at Data Formatters temporarily unavailable, will re-try after a 'continue'.
"Data Formatters temporarily unavailable, will re-try after a
'continue'." means that something has gone so horribly wrong in your
code that even the debugger bailed. As dragyn said, this usually
involves some form of rapid object creation or recursion calling. Add
a few NSLog lines into your code to help you see how far your code is
getting and where it might be looping/calling itself.

Mac App Store Reviewer says "It appears Kiwi fails codesign verification"

But it clearly does not fail on my system. The Verification test in XCode during the submission should (I assume) test this. And running codesign on the command line of the archived app results in:
/Users/iac/Library/Application Support/Developer/Shared/Archived Applications/272860A0-961E-47E7-B62F-0F7D373D938A.apparchive/Kiwi.app: valid on disk
/Users/iac/Library/Application Support/Developer/Shared/Archived Applications/272860A0-961E-47E7-B62F-0F7D373D938A.apparchive/Kiwi.app: satisfies its Designated Requirement
Anyone run into something like this before?
Thanks,
Isaiah
After a bit of back and forth the app was placed back "In Review" (without any change to the binary). It was then rejected again for another odd reason (No non-apple installers allowed) after which it was again placed back "In Review," (again without any changes to the binary).
After a few more emails it finally received a rejection that made sense: a few files in my resource folder had overly restrictive permissions.
So the answer is: double-check your file permissions or be doomed to weeks of confusion.
Isaiah

Mac OS X: Getting detailed process information (specifically its launch arguments) for arbitrary running applications using its PID

I am trying to detect when particular applications are launched.
Currently I am using NSWorkspace, registering for the "did launch application" notification. I also use the runningApplications method to get apps that are currently running when my app starts.
For most apps, the name of the app bundle is enough. I have a plist of "known apps" that I cross check with the name of that passed in the notification.
This works fine until you come across an app that acts as a proxy for launching another application using command line arguments.
Example: The newly released Portal on the Mac doesn't have a dedicated app bundle. Steam can create a shortcut, which serves as nothing more than to launch the hl2_osx app with the -game argument and portal as it's parameter.
Since more Source based games are heading to the Mac, I imagine they'll use the same method to launch, effectively running the hl2_osx app with the -game argument.
Is there a nice way to get a list of the arguments (and their parameters) using a Cocoa API?
NSProcessInfo comes close, offering an `-arguments' method, but only provides information for its own process...
NSRunningApplication offers the ability to get information about arbitrary apps using a PID, but no command line args...
Is there anything that fills the gap between the two?
I'm trying not to go down the route of spawning an NSTask to run ps -p [pid] and parsing the output... I'd prefer something more high level.
You could use whatever ps uses, though it isn't cocoa based. According to Singh, ps is based on kvm and sysctl calls. Pouring over the source, the pertinant calls seem to be kvm_openfiles, kvm_getprocs and kvm_getargv. To get the command line arguments, first call kvm_openfiles to get access to the kernel memory space, then use kvm_getprocs to get kernel process info, then kvm_getargv.
The use of sysctl in ps seems less relevant to your goal; it's used to get other information, such as the group ID and parent proces ID. The particular sysctl name used is {CTL_KERN, KERN_PROC, KERN_PROC_which, flags}, where which specifies a process filter (e.g. ALL, PID) and flags are arguments for the filter (the details are in the sysctl man page).
OS X doesn't have support procfs, but Singh developed a FUSE based version, released under GPLv2. If you bundle it with your application, you'll have to release it under GPLv2 as well. Most of MacFUSE is released under a BSD-style license, so it can be distributed with your app without making it open source (fusefs/fuse_nodehash.c is released under Apple's open source license, but it also allows linking to closed source apps).
The question "Get other process' argv in OS X using C" should be of use, as it has sample code using kvm and sysctl. TN 2050 "Observing Process Lifetimes Without Polling" may also be of use to you.
Nope - running ps is your best bet. Standard process info interfaces aren't supported on OS X (noop versions were provided in OS X 10.4, but removed thereafter) and the private interfaces are likely to change between OS X revisions.
If you're willing to lock yourself into a single OS X version, all the source is available, for example for ps or libproc; you'll also need to run as root.