Recently a bunch of folks have asked about why a specific symbol is being referenced by their app. This is my attempt to address that question.
If you have questions or comments, please start a new thread. Tag it with Linker so that I see it.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"
Determining Why a Symbol is Referenced
In some situations you might want to know why a symbol is referenced by your app. For example:
You might be working with a security auditing tool that flags uses of malloc.
You might be creating a privacy manifest and want to track down where your app is calling stat.
This post is my attempt at explaining a general process for tracking down the origin of these symbol references. This process works from ‘below’. That is, it works ‘up’ from you app’s binary rather than ‘down’ from your app’s source code. That’s important because:
It might be hard to track down all of your source code, especially if you’re using one or more package management systems.
If your app has a binary dependency on a static library, dynamic library, or framework, you might not have access to that library’s source code.
IMPORTANT This post assumes the terminology from An Apple Library Primer. Read that before continuing here.
The general outline of this process is:
Find all Mach-O images.
Find the Mach-O image that references the symbol.
Find the object files (.o) used to make that Mach-O.
Find the object file that references the symbol.
Find the code within that object file.
This post assumes that you’re using Xcode. If you’re using third-party tools that are based on Apple tools, and specifically Apple’s linker, you should be able to adapt this process to your tooling. If you’re using a third-party tool that has its own linker, you’ll need to ask for help via your tool’s support channel.
Find all Mach-O images
On Apple platforms an app consists of a number of Mach-O images. Every app has a main executable. The app may also embed dynamic libraries or frameworks. The app may also embed app extensions or system extensions, each of which have their own executable. And a Mac app might have embedded bundles, helper tools, XPC services, agents, daemons, and so on.
To find all the Mach-O images in your app, combine the find and file tools. For example:
% find "Apple Configurator.app" -print0 | xargs -0 file | grep Mach-O
Apple Configurator.app/Contents/MacOS/Apple Configurator: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64]
…
Apple Configurator.app/Contents/MacOS/cfgutil: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
…
Apple Configurator.app/Contents/Extensions/ConfiguratorIntents.appex/Contents/MacOS/ConfiguratorIntents: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64:Mach-O 64-bit executable arm64]
…
Apple Configurator.app/Contents/Frameworks/ConfigurationUtilityKit.framework/Versions/A/ConfigurationUtilityKit: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64]
…
This shows that Apple Configurator has a main executable (Apple Configurator), a helper tool (cfgutil), an app extension (ConfiguratorIntents), a framework (ConfigurationUtilityKit), and many more.
This output is quite unwieldy. For nicer output, create and use a shell script like this:
% cat FindMachO.sh
#! /bin/sh
# Passing `-0` to `find` causes it to emit a NUL delimited after the
# file name and the `:`. Sadly, macOS `cut` doesn’t support a nul
# delimiter so we use `tr` to convert that to a DLE (0x01) and `cut` on
# that.
#
# Weirdly, `find` only inserts the NUL on the primary line, not the
# per-architecture Mach-O lines. We use that to our advantage, filtering
# out the per-architecture noise by only passing through lines
# containing a DLE.
find "$@" -type f -print0 \
| xargs -0 file -0 \
| grep -a Mach-O \
| tr '\0' '\1' \
| grep -a $(printf '\1') \
| cut -d $(printf '\1') -f 1
Find the Mach-O image that references the symbol
Once you have a list of Mach-O images, use nm to find the one that references the symbol. The rest of this post investigate a test app, WaffleVarnishORama, that’s written in Swift but uses waffle management functionality from the libWaffleCore.a static library. The goal is to find the code that calls calloc.
This app has a single Mach-O image:
% FindMachO.sh "WaffleVarnishORama.app"
WaffleVarnishORama.app/WaffleVarnishORama
Use nm to confirm that it references calloc:
% nm "WaffleVarnishORama.app/WaffleVarnishORama" | grep "calloc"
U _calloc
The _calloc symbol has a leading underscore because it’s a C symbol. This convention dates from the dawn of Unix, where the underscore distinguish C symbols from assembly language symbols.
The U prefix indicates that the symbol is undefined, that is, the Mach-O images is importing the symbol. If the symbol name is prefixed by a hex number and some other character, like T or t, that means that the library includes an implementation of calloc. That’s weird, but certainly possible. OTOH, if you see this then you know this Mach-O image isn’t importing calloc.
IMPORTANT If this Mach-O isn’t something that you build — that is, you get this Mach-O image as a binary from another developer — you won’t be able to follow the rest of this process. Instead, ask for help via that library’s support channel.
Find the object files used to make that Mach-O image
The next step is to track down which .o file includes the reference to calloc. Do this by generating a link map. A link map is an old school linker feature that records the location, size, and origin of every symbol added to the linker’s output.
To generate a link map, enable the Write Link Map File build setting. By default this puts the link map into a text (.txt) file within the derived data directory. To find the exact path, look at the Link step in the build log. If you want to customise this, use the Path to Link Map File build setting.
A link map has three parts:
A simple header
A list of object files used to build the Mach-O image
A list of sections and their symbols
In our case the link map looks like this:
# Path: …/WaffleVarnishORama.app/WaffleVarnishORama
# Arch: arm64
# Object files:
[ 0] linker synthesized
[ 1] objc-file
[ 2] …/AppDelegate.o
[ 3] …/MainViewController.o
[ 4] …/libWaffleCore.a[2](WaffleCore.o)
[ 5] …/Foundation.framework/Foundation.tbd
…
# Sections:
# Address Size Segment Section
0x100008000 0x00001AB8 __TEXT __text
…
The list of object files contains:
An object file for each of our app’s source files — That’s AppDelegate.o and MainViewController.o in this example.
A list of static libraries — Here that’s just libWaffleCore.a.
A list of dynamic libraries — These might be stub libraries (.tbd), dynamic libraries (.dylib), or frameworks (.framework).
Focus on the object files and static libraries. The list of dynamic libraries is irrelevant because each of those is its own Mach-O image.
Find the object file that references the symbol
Once you have list of object files and static libraries, use nm to each one for the calloc symbol:
% nm "…/AppDelegate.o" | grep calloc
% nm "…/MainViewController.o" | grep calloc
% nm "…/libWaffleCore.a" | grep calloc
U _calloc
This indicates that only libWaffleCore.a references the calloc symbol, so let’s focus on that.
Note As in the Mach-O case, the U prefix indicates that the symbol is undefined, that is, the object file is importing the symbol.
Find the code within that object file
To find the code within the object file that references the symbol, use the objdump tool. That tool takes an object file as input, but in this example we have a static library. That’s an archive containing one or more object files. So, the first step is to unpack that archive:
% mkdir "libWaffleCore-objects"
% cd "libWaffleCore-objects"
% ar -x "…/libWaffleCore.a"
% ls -lh
total 24
-rw-r--r-- 1 quinn staff 4.1K 8 May 11:24 WaffleCore.o
-rw-r--r-- 1 quinn staff 56B 8 May 11:24 __.SYMDEF SORTED
There’s only a single object file in that library, which makes things easy. If there were a multiple, run the following process over each one independently.
To find the code that references a symbol, run objdump with the -S and -r options:
% xcrun objdump -S -r "WaffleCore.o"
…
; extern WaffleRef newWaffle(void) {
0: d10083ff sub sp, sp, #32
4: a9017bfd stp x29, x30, [sp, #16]
8: 910043fd add x29, sp, #16
c: d2800020 mov x0, #1
10: d2800081 mov x1, #4
; Waffle * result = calloc(1, sizeof(Waffle));
14: 94000000 bl 0x14 <ltmp0+0x14>
0000000000000014: ARM64_RELOC_BRANCH26 _calloc
…
Note the ARM64_RELOC_BRANCH26 line. This tells you that the instruction before that — the bl at offset 0x14 — references the _calloc symbol.
IMPORTANT The ARM64_RELOC_BRANCH26 relocation is specific to the bl instruction in 64-bit Arm code. You’ll see other relocations for other instructions. And the Intel architecture has a whole different set of relocations. So, when searching this output don’t look for ARM64_RELOC_BRANCH26 specifically, but rather any relocation that references _calloc.
In this case we’ve built the object file from source code, so WaffleCore.o contains debug symbols. That allows objdump include information about the source code context. From that, we can easily see that calloc is referenced by our newWaffle function.
To see what happens when you don’t have debug symbols, create an new object file with them stripped out:
% cp "WaffleCore.o" "WaffleCore-stripped.o"
% strip -x -S "WaffleCore-stripped.o"
Then repeat the objdump command:
% xcrun objdump -S -r "WaffleCore-stripped.o"
…
0000000000000000 <_newWaffle>:
0: d10083ff sub sp, sp, #32
4: a9017bfd stp x29, x30, [sp, #16]
8: 910043fd add x29, sp, #16
c: d2800020 mov x0, #1
10: d2800081 mov x1, #4
14: 94000000 bl 0x14 <_newWaffle+0x14>
0000000000000014: ARM64_RELOC_BRANCH26 _calloc
…
While this isn’t as nice as the previous output, you can still see that newWaffle is calling calloc.
General
RSS for tagDive into the vast array of tools and services available to developers.
Post
Replies
Boosts
Views
Activity
Hello there:
On November 2023, I submitted enrollment ID 3BR28NV28U. I am responsible on behalf of my employer, Strathcona Resources, to submit this Apple Developer enrollment to advance in a custom app that we must implement to our iPads in our field sites. As you can probably tell, I have not received any advancement with this request, and seven months have passed, without any update or any notification regarding this enrollment.
I would appreciate it if you can please channel this request to the appropriate party, in order to provide a status update, escalation, and completion as appropriate.
Seven months without an update is a major delay, and we are behind schedule for the custom app that we need to implement in our organization.
Thank you for your attention to this matter.
Best regards,
**** Godoy
Strathcona Resources
Assuming I have a static library where all global symbols need to be re-exported by the target executable. How do I extract these symbols into a file to be used with ld's -exported_symbols_list and Xcode's EXPORTED_SYMBOLS_FILE?
I was thinking about nm -gUjo … + sed but maybe there is abetter way?
Hi,
Guys, I would lie to ask it been more than 10 days I add my card but still it shows
Your purchase may take up to 48 hours to process. i use my name same in card also
anybody know what possible issues here, i was using my email but it is not same email with my card
I located in Malaysia
Hi, I want to create an offline mode for my iOS app. Where is it better to keep files in terms of download speed: in a CDN like Cloudflare or using On-Demand Resources? The total file size is 2 GB.
Hi, ho un'idea per un'applicazione che può rivoluzionare e agevolare riguardo l'utilizzo degli apparati video (telefoni, monitor, tv) per almeno il75/80% dell'intera popolazione mondiale.
Vorrei che fosse un'operazione realizzata inizialmente da apple ios/os e in seguito su tutti i supporti.
Mi piacerebbe creare, sviluppare o cedere l'idea ma non so proprio da dove iniziare.
potete darmi info su questo?
so che può sembrare una richiesta astrana, ma sono certo che questa app sarà una vera rivoluzione per tutti, o quasi
Grazie
Giovanni da Cagliari, Sardegna, Italia
Hi, I have an idea for an application that can revolutionize and facilitate the use of video equipment (telephones, monitors, TVs) for at least 75/80% of the entire world population.
I would like it to be an operation carried out initially by apple ios/os and later on all media.
I would like to create, develop or sell the idea but I really don't know where to start.
can you give me info on this?
I know it may seem like a strange request, but I'm sure that this app will be a real revolution for everyone, or almost everyone
Thank you
Giovanni from Italy
[Edited by Moderator]
Hi all ,
We are planning to manage about 1 Million+ Apple devices of inclusive of both iPhone and Mac devices under a AxM Account. However while adding VPP Licenses for an App i'm prompted with below error:
" You cannot order more than 100000 copies of same the free item per week"
While our goal is to manage 1 Million devices under same Location token , i have below questions in mind
1 . What is the upper limit of number of Licenses that can be added per app in a Location token?
Currently it says 1 Lakh Licenses per app per week . Wanted to know if there is any limit on this count as it shouldn't surprise us in upcoming weeks.
2 . How many Locations can be created in a AxM Account?
Currently we created about 15 location to see if there are any limit but so far couldn't find any limit on number of locations that can be created. This limit could help us plan our deployment in advance
3 . What is the total number of licenses a VPP Location token can hold ?
As we manage 1 Million Devices for 12 Apps , 1 Million x 12= 12 Million licenses would be transacted in this location token by our MDM Solution , is this okay or will there be any limitations in this count
I'm looking for a way (hopefully with a compiler directive) - in debug mode as well as in my UITests - to determine if a GPX file is being used. You use a GPX file for simulating location - it is set within the scheme settings under "Core Location - Allow Location Simulation".
Is this possible?
I'm trying to compile a little project in C with the following structure:
Project
|
|->Headers
|->library.h
|
|->src
|->main.c
|->library.c
I've checked all my files, my configurations files and I'm getting the same error everytime, someone could please help me? :(
Undefined symbols for architecture arm64:
"_getfavoritenumber", referenced from:
_main in main-99c109.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I have integrated MetricKit into my production app and listening for the corresponding callback
func didReceive(_ payloads: [MXDiagnosticPayload])
After some time, I've noticed that the hang diagnostics data collected are all for hangs longer than 1 second.
Does MetricKit only collect hang data for hangs longer than 1 second?
Can this threshold be adjusted, for example, to 500ms?
Is there any sampling involved in the collection of hang diagnostics? The number of hang events collected by MetricKit is significantly lower compared to other third-party platforms.
Thank you for your response, this is very important to me.
Cx was unable to login to their cloud account when the policy was pushed on to their device. However, when no policy was pushed cx could login. The issue is with applying whitelist configuration to device with passcode turned on..while whitelisting the app some system bundle identifier is getting blocked, we tried whitelisting all system app available for ios and couldn't find a solution
We are considering developing our own MDM server for internal app distribution.
Is it necessary to enroll in the Apple Enterprise Developer Program to develop MDM server?
Currently, our company is only enrolled in the Apple Developer Program and Business Manager.
Additionally, since we have fewer than 100 employees, it is difficult for us to join the Enterprise Program. In this case, is it not possible for us to set up an MDM server?
I want to run my custom application on my VisionPro.
I have paired my VisionPro with Xcode successfully but when I am running it it shows me to enable developer mode in VisionPro.
When I followed the options and Went to Settings -> Privacy & Security.
There is no developer mode option visible at any place.
Please let me know how I can enable the developer option in VisionPro.
Thanks
I am using HTTP Live Streaming Tools to segment a spatial video (MV-HEVC) recorded by Vision Pro. I first used the macOS build on my MacBook, it works beautifully with the command:
mediafilesegmenter -r -f path/to/destination path/to/movie.MOV
But when I tried to use the CentOS build in a Docker container and segment the exact same file using the exact same command, it gives the following error:
can't create format reader /path/to/movie.MOV 561211770
Unable to find any valid tracks to segment.
I looked up the error code, it seems to correspond to kAudioSessionBadPropertySizeError. Any idea why?
hello;
The simulator exists but not in xcode 15.4?
why?
Why do we need to review the formatting for different versions of xcode, the same for development for MAC and IOS? This xcode bug too often. Still poorly documented.
My project is visionOS project. I add the package ‘swift-openapi-generator’ and add run build tool plug-ins as the vedio teached. When I build the project, xcode show me the error No such module 'Glibc'
A highly-effective debugging technique is to create a test project focused on your issue, and iterate on solutions using only the test project. We often ask developers to provide us with a small Xcode test project because it helps focus a discussion on the relevant Apple APIs.
An ideal test project:
Focuses only on specific Apple APIs
Uses the minimum amount of code possible (usually just a few files)
Reliably demonstrates the problem for anyone who builds the project
Contains no third-party libraries
Builds with no warnings using Xcode's default build settings
Does not require any third-party build tools
There are two approaches to creating a focused Xcode project:
Create a new project starting from one of Xcode's built-in templates, and add code to demonstrate the issue.
Start with a copy of your existing project, and remove code not essential to the issue. Remove code iteratively, re-testing after every removal. If you find that you can no longer demonstrate the issue after removing a particular piece of code, it’s likely that the issue is within the last-removed code. After restoring this code to the project, keep reducing the surrounding code until everything remaining is essential to the issue.
The first method is often faster if you can quickly find the right functionality to add. If that doesn't work out, the second method is usually a reliable approach.
In many cases, creating the test project will help you locate and solve the issue by yourself. Even if it doesn't, the test project still has value! It provides a smaller starting point for others to look into your issue. And if the test project helps identify a bug, then you can attach it to a bug report; the engineer looking at your report will appreciate the effort.
Sharing a link to a test project
We're always willing to take a look at your test project when it satisfies the characteristics listed above. Just share a link to where we can find it as part of your post. The forums have a list of websites you can link to. If you find that your link isn't visible in the preview of your post, just include the URL without using Markdown link syntax. For example, this link with Markdown won't appear:
Apple is based in [Cupertino](https://www.cupertino.org).
but this version will:
Apple is based in Cupertino.
https://www.cupertino.org
Revision History
2024-05-30 Initial version.
When making a disk image for software distribution, it used to be possible to make a Finder window automatically open when the disk image is mounted, using a command like
sudo bless --folder dirPath --openfolder dirPath
on a read-write disk image.
However, as of Ventura, attempting to do so produces an error message
bless: The 'openfolder' option is deprecated
and the command fails to do what I want.
Disk images that were set up this way in years past continue to work. I suppose I could duplicate a working writable disk image, remove the old contents and put in new contents, but that seems a little hacky. Is there an alternative?
Tested on: iPhone11+iOS16.5/iPhoneXS+iOS15.4.
Compile with: XCode12/13/14.
I tried following code, compile with arch=arm64e only, and result in crash "EXC_BAD_ACCESS". at "LDRAA"
std::cout << "";
The crash will not be triggered if:
compile with arch=arm64 only
compile with arch=arm64e only and tested on iOS<=14
not use any c++ I/O api
Is there a way to give a default text color to tags in apple news format. I'm testing this in Apple News Preview currently, and I can't figure out what's wrong.
According to the documentation, I should be able to style the tag using "default-tag-a"
https://developer.apple.com/documentation/apple_news/apple_news_format/components/using_html_with_apple_news_format#2992870
However, this doesn't appear to work. It works perfectly when I do paragraph tags like "default-tag-p" or span tags like "default-tag-span".
Maybe, I'm missing something. Here is my code
"textStyles": {
"default-tag-a": {
"textColor": "#1967d2"
}
}
when I add a font like
"textStyles": {
"default-tag-a": {
"fontName": "Georgia",
"textColor": "#1967d2"
}
}
This does change the font. So i'm wondering can I change the text color for links in apple news? and if so, how?
Thanks for your assistance.