Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Steps to get GDB actually working in April 2021 on macOS (Intel x86-64 only)

Debug with GDB on macOS 11

The big reason to do this is that LLDB has no ability to "follow-fork-mode child", in other words, a multi-process target that doesn't have a single-process mode (or, a bug that only manifests when in multi-process mode) is going to be difficult or impossible to debug, especially if you have to run the target over and over in order to make the bug manifest. If you have a repeatable bug, no big deal, break on the fork from the parent process and attach to the child in a second lldb instance. Otherwise, read on.

Install GDB

Don't make the mistake of thinking you can just brew install gdb. Currently this is version 10.2 and it's mostly broken, with at least two annoying bugs as of April 29th 2021, but the big one is https://sourceware.org/bugzilla/show_bug.cgi?id=24069

$ xcode-select install  # install the XCode command-line tools
$ brew install --force --build-from-source domq/gdb/gdb  # a patched version based on 10.1

It's now installed at /usr/local/bin/gdb.

Create and Install a Self-Signed Code-Signing Certificate

  1. Start the Keychain Access application, found in /Applications/Utilities.
  2. From the Keychains list on the left, right-click on the System item and select Unlock Keychain "System".
  3. Choose Keychain Access > Certificate Assistant > Create a Certificate... from the menu.
  4. Choose a name (e.g. gdb-cert), set Identity Type to Self Signed Root, set Certificate Type to Code Signing and select the Let me override defaults. Click several times on Continue until you get to the Specify a Location For The Certificate screen, then set Keychain to System.
  5. If for some reason you create the certificate in the System keychain directly, create it in the Login keychain, then export it. You can then import it into the System keychain.
  6. Finally, using the context menu for the certificate, select Get Info, open the Trust item, and set Code Signing to Always Trust.
  7. From the Keychains list on the left, right-click on the System item and select Lock Keychain "System".
  8. You must quit the Keychain Access application and restart the system, in order to use the certificate.

Create the entitlements plist file (for macOS 10.14 and newer)

We'll call it gdb-entitlement.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.disable-executable-page-protection</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>

Codesign and entitle the GDB executable

$ codesign --entitlements gdb-entitlement.xml -fs gdb-cert $(which gdb)

This seems to work even though that's Homebrew's link to the actual file on disk:

% ls -la $(which gdb)
lrwxr-xr-x  1 mmyers  admin  26 Apr 28 16:16 /usr/local/bin/gdb -> ../Cellar/gdb/10.2/bin/gdb
% codesign -vvv /usr/local/Cellar/gdb/10.2/bin/gdb
/usr/local/Cellar/gdb/10.2/bin/gdb: valid on disk
/usr/local/Cellar/gdb/10.2/bin/gdb: satisfies its Designated Requirement

Finally, Run GDB

$ gdb hello_world
(gdb) break main
(gdb) run

Troubleshooting

  • GDB will not understand "fat" executables. You can "lipo -thin x86_64" them.
  • If you tried debugging with gdb, but you get a "No symbol table is loaded" error, you might need to compile programs with the -ggdb option in gcc. I didn't have this issue personally.
  • If after hitting run in gdb, you get "Starting program: /path/to/your/executable [args] [New Thread 0x2303 of process 795]" followed by a blank line which does not respond to anything, then you have hit GDB bug 24069. Check that you built the patched version from source.
@fabiokon
Copy link

fabiokon commented Oct 22, 2021

i just installed it successfully on Mojave 10.14.6 and debugging works again. I didn't update cmd line tools though

I'm trying on Big Sur 11.6 and the result is:

Warning: No available formula with the name "python@3.9" (dependency of domq/gdb/gdb).
==> Searching for similarly named formulae...
Error: No similarly named formulae found.
==> Searching for a previously deleted formula (in the last month)...
Error: No previously deleted formula found.
==> Searching taps on GitHub...
Error: No formulae found in taps.

@srwarner
Copy link

srwarner commented Oct 22, 2021

@bojomojo
Copy link

bojomojo commented Nov 22, 2021

I am trying this now to get gdb running on eclipse, and always getting stuck on 96%..
I added the gdb binary to privacy & security -> developer tools
I am using the absolute path for gdb in both, the entitlements command and eclipse
I am running eclipse as sudo..

And I get stuck at: list-thread-groups..
Note, this is not the first time -list-thread-groups is called.. it was called before, and worked fine. Seems this happens after -exec-run is executed

so I have 33-exec-run, with no "DONE" for it. And then 34-list-thread-groups, and it hangs there.

@Tzu-Yao
Copy link

Tzu-Yao commented Jan 16, 2022

Hi! Thanks for the instruction!

I'm following it to address the code signing issue but a little confused about creating the "entitlements plist file:"
I wonder where do I create this "gdb-entitlement.xml" file?

Thank you!

@CornPrincess
Copy link

CornPrincess commented Jan 20, 2022

Works well for me on Mac OSX 11.2 Big Sur! Thanks!

@mike-myers-tob
Copy link
Author

mike-myers-tob commented Jan 20, 2022

I'm following it to address the code signing issue but a little confused about creating the "entitlements plist file:"
I wonder where do I create this "gdb-entitlement.xml" file?

Hi Tzu-Yao. This is a file you can create anywhere and call it whatever you want, but I chose gdb-entitlement.xml. Fill it with the XML you see in my original gist, and it is used in the next step when invoking codesign in the argument --entitlements gdb-entitlement.xml

@jacksonwelsh
Copy link

jacksonwelsh commented Feb 8, 2022

Hmm I'm on 12.1 Monterey and getting the following error:

λ brew install --force --build-from-source domq/gdb/gdb
==> Downloading https://ftp.gnu.org/gnu/gdb/gdb-10.1.tar.xz
Already downloaded: /Users/jacksonwelsh/Library/Caches/Homebrew/downloads/d6dfd55ca620ab89b3209b96be8cac6a9b85c636faf527f4c5e4bc7e7ff07cee--gdb-10.1.tar.xz
==> Installing gdb from domq/gdb
==> Patching
==> ../configure --enable-targets=all --prefix=/opt/homebrew/Cellar/gdb/10.1_1 -
==> make
==> make install-gdb maybe-install-gdbserver
Error: Empty installation

thoughts? this is on an M1 Pro MacBook Pro

@phil-blain
Copy link

phil-blain commented Feb 9, 2022

Hi @jacksonwelsh! Unfortunately GDB does not yet support the M1 chip. The build succeeds (does not fail) but the GDB executable is not built, which I guess is what causes the Brew error "empty installation".

@phil-blain
Copy link

phil-blain commented Feb 9, 2022

@mike-myers-tob A note about the entitlements, the only really neeeded entitlement is com.apple.security.cs.debugger, which lets the system know that GDB is a debugger and can control other processes.

It is a good idea to also add com.apple.security.get-task-allow, which lets the system know that other processes are allowed to debug the GDB binary (e.g. if you want to debug GDB using LLDB, or another GDB instance). The other entitlements are not needed at all in my experience.

@michaelschem
Copy link

michaelschem commented Feb 17, 2022

@jacksonwelsh did you ever find a solution? I'm having the same issue.

@gromgit
Copy link

gromgit commented Feb 21, 2022

@michaelschem As @phil-blain already mentioned:

GDB does not yet support the M1 chip

The instructions above that do work are for GDB on Intel macOS.

@phil-blain
Copy link

phil-blain commented Mar 3, 2022

Hi everyone, the fixes that Dominique Quatravaux (@domq) incorporated in their fork of GDB, made available in the Homebrew tap linked above by @mike-myers-tob (at https://github.com/domq/homebrew-gdb), were merged recently to the upstream GDB project:

This means that you should be able to get a working GDB on recent macOS by building from source, which should be as easy as this:

date="$(date +%Y%m%d)"
curl -sSLO https://sourceware.org/pub/gdb/snapshots/current/gdb-12.0.50.${date}.tar.xz
tar xf gdb-12.0.50.${date}.tar.xz
mkdir build
cd build
../gdb-12.0.50.${date}/configure \
    --disable-unit-tests         \
    --disable-binutils           \
    --without-guile
make -j
make install
echo 'set startup-with-shell off' >> $HOME/.gdbinit

and then signing the executable as mentioned above. Disabling unit-tests should not affect GDB's functionality and is required to work around this bug.

It would be really great if interested people could try it and see if the hang is resolved. It is from my testing on macOS 10.15 but I do not have access to other versions to test. Please do try it and report back on the bugzilla issue (https://sourceware.org/bugzilla/show_bug.cgi?id=24069) if the hang is not resolved.

EDIT changed the commands above to use date so they can be copy pasted as-is.
EDIT added --without-guile

@zouhairm
Copy link

zouhairm commented Mar 7, 2022

Running into this issue. I'm on macOS 10.15.7.
Tried the following:

  • downloaded gdb-12.0.50.20220307 & unzipped
mkdir build
cd build
../gdb-12.0.50.20220307/configure --with-pydebug --disable-unit-tests   --disable-binutils
make -j

Getting this error:

../../gdb-12.0.50.20220307/gdb/guile/guile.c:676:5: error:
      'scm_install_gmp_memory_functions' is deprecated [-Werror,-Wdeprecated-declarations]
    scm_install_gmp_memory_functions = 0;
    ^
/usr/local/Cellar/guile/3.0.8/include/guile/3.0/libguile/deprecated.h:164:1: note:
      'scm_install_gmp_memory_functions' has been explicitly marked deprecated here
SCM_DEPRECATED int scm_install_gmp_memory_functions;
^
/usr/local/Cellar/guile/3.0.8/include/guile/3.0/libguile/scm.h:743:50: note: expanded from
      macro 'SCM_DEPRECATED'
# define SCM_DEPRECATED  SCM_API __attribute__ ((__deprecated__))
                                                 ^
1 error generated.
make[2]: *** [guile/guile.o] Error 1
make[2]: *** Waiting for unfinished jobs....
``

@phil-blain
Copy link

phil-blain commented Mar 7, 2022

If you don’t need Guile scripting capabilities, try removing the build directory and rerunning configure with --without-guile

@iceice
Copy link

iceice commented Mar 27, 2022

Hi everyone, the fixes that Dominique Quatravaux (@domq) incorporated in their fork of GDB, made available in the Homebrew tap linked above by @mike-myers-tob (at https://github.com/domq/homebrew-gdb), were merged recently to the upstream GDB project:

This means that you should be able to get a working GDB on recent macOS by building from source, which should be as easy as this:

date="$(date +%Y%m%d)"
curl -sSLO https://sourceware.org/pub/gdb/snapshots/current/gdb-12.0.50.${date}.tar.xz
tar xf gdb-12.0.50.${date}.tar.xz
mkdir build
cd build
../gdb-12.0.50.${date}/configure \
    --disable-unit-tests         \
    --disable-binutils           \
    --without-guile
make -j
make install
echo 'set startup-with-shell off' >> $HOME/.gdbinit

and then signing the executable as mentioned above. Disabling unit-tests should not affect GDB's functionality and is required to work around this bug.

It would be really great if interested people could try it and see if the hang is resolved. It is from my testing on macOS 10.15 but I do not have access to other versions to test. Please do try it and report back on the bugzilla issue (https://sourceware.org/bugzilla/show_bug.cgi?id=24069) if the hang is not resolved.

EDIT changed the commands above to use date so they can be copy pasted as-is. EDIT added --without-guile

Thanks for @phil-blain tutorial, but the gdb hangs on macOS Catalina(10.15.7) at the very first excution, run gdb again, it works well.

How can I avoid it?

@phil-blain
Copy link

phil-blain commented Mar 27, 2022

Thanks for @phil-blain tutorial, but the gdb hangs on macOS Catalina(10.15.7) at the very first excution, run gdb again, it works well.

How can I avoid it?

Thanks for trying it! I also noticed that behaviour. Unfortunately I can't tell you how to avoid it since it appears the GDB bug is not yet completely fixed. The only way to avoid it would be to fix GDB. This would require understanding the Darwin/Mach kernel debug API and trying to assess what goes wrong in the GDB code base. Since GDB works correctly on macOS 10.13 and below, I'm assuming something changed in the macOS kernel behaviour between 10.13 and 10.14 which leads to the wrong behaviour being observed here...

@hitzhangjie
Copy link

hitzhangjie commented Apr 10, 2022

Can anyone submit a built gdb binary here, I am using macOS 10.15.7. My network is so slow to pull the gdb source code.


I solved this by:

  1. download the source code zip file from https://github.com/bminor/binutils-gdb.git,
    unzip the zipfile to ./binutils-gdb-master
  2. then try to build from master HEAD
mkdir build
cd build
../binutils-gdb-master/configure \
    --disable-unit-tests         \
    --disable-binutils           \
    --without-guile
make -j8

the built gdb binary is put here: ./gdb/gdb

Because I want to make package management simpler, so I don't want to run make install to install the gdb and other files.

ps: there's no make uninstall target in the Makefile, if you want to remove all installed files, try this:

make install DESTDIR=/tmp/gccinst
find /tmp/gccinst | sed -e s,/tmp/gccinst,, | \
(while read F; do rm "$F"; done)
  1. I then run brew install gdb to install the homebrew latest version, then I replace the gdb binary by:
cp ./gdb/gdb /usr/local/Cellar/gdb/11.2/bin/gdb -f
  1. Then codesign mentioned above, OK, I put it here for convenience:
    write a gdb-entitlement.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
    <true/>
    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
    <true/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
    <key>com.apple.security.cs.disable-executable-page-protection</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
    <key>com.apple.security.get-task-allow</key>
    <true/>
</dict>
</plist>

then run following command to codesign:

sudo codesign --entitlements gdb-entitlement.xml -fs gdb-cert $(which gdb)

If you don't have a gdb-cert created before, run following command to create one:

# download the script
https://github.com/conda-forge/gdb-feedstock/blob/main/recipe/macos-codesign/macos-setup-codesign.sh

# replace the certificate name
sed -i 's/gdb-codesign/gdb-cert/g' macos-setup-codesign.sh

# run the script to create the certificate and trust it
./macos-setup-codesign.sh

# check the certificate is create or not
security find-certificate -p -c gdb-cert | openssl x509 -checkend 0
or
security find-certificate -p -c gdb-cert |openssl x509 -noout -text\
  1. then you can start your debugging, it works.

@phil-blain
Copy link

phil-blain commented May 5, 2022

GDB 12.1 was released last weekend, which includes the patches mentioned above. You can build it yourself from the tarball, or use brew install gdb since Homebrew has already built this new version.

@petrstepanov
Copy link

petrstepanov commented Jun 7, 2022

@mike-myers-tob thank you for this write up! I also confirm that above approach works with Eclipse 2022-03 (4.23.0) and GNU gdb (GDB) 12.1 installed from brew install gdb

@aditya-solana
Copy link

aditya-solana commented Aug 17, 2022

On MacOS 12.5
MacBook Pro (16-inch, 2021) M1 Max

$ brew install gdb
gdb: The x86_64 architecture is required for this software.
Error: gdb: An unsatisfied requirement failed this build.

@michaelschem
Copy link

michaelschem commented Aug 17, 2022

The hint is in the error x86_64 architecture is required for this software., you're on an M1 mac. Not gonna work.

@4nuG
Copy link

4nuG commented Aug 21, 2022

@michaelschem im on a 2022 m2 Mac and I get the same error:
% brew install gdb
gdb: The x86_64 architecture is required for this software.

@michaelschem
Copy link

michaelschem commented Aug 21, 2022

@4nuG same problem. All mac chips (those starting with M) are arm and not x86_64.

@siddharth7061
Copy link

siddharth7061 commented Oct 11, 2022

Hi I am using macOS Catalina 10.15.7
I had to create the certificate in login as it was showing error while doing it in system. How do i import it to system, please explain.

@mayakrunal
Copy link

mayakrunal commented Oct 12, 2022

@siddharth7061 I think you can just import it into key chain, if it's on your local laptop.

https://support.apple.com/guide/keychain-access/add-certificates-to-a-keychain-kyca2431/mac

@mayakrunal
Copy link

mayakrunal commented Oct 12, 2022

@ferdnyc
Copy link

ferdnyc commented Oct 21, 2022

# download the script
https://github.com/conda-forge/gdb-feedstock/blob/main/recipe/macos-codesign/macos-setup-codesign.sh

# replace the certificate name
sed -i 's/gdb-codesign/gdb-cert/g' macos-setup-codesign.sh

@hitzhangjie

Note that, at least with the current version of https://github.com/conda-forge/gdb-feedstock/blob/main/recipe/macos-codesign/macos-setup-codesign.sh, that sed command should be:

sed -i 's/gdb_codesign/gdb-cert/g' macos-setup-codesign.sh

Since the script (now?) uses an underscore instead of a dash.

Probably makes sense to do this, in fact:

sed -i 's/gdb_codesign/gdb_cert/g' macos-setup-codesign.sh

And then use the name gdb_cert instead.

@optimux
Copy link

optimux commented Nov 27, 2022

Hang issue:
If after hitting run in gdb, you get "Starting program: /path/to/your/executable [args] [New Thread 0x2303 of process 795]" followed by a blank line which does not respond to anything, then you have hit GDB bug 24069.

This problem has an easy fix, type in terminal:
echo "set startup-with-shell-off" >> ~/.gdbinit
source ~/.gdbinit

Restart gdb you'll find it's working. This issue is quite annoying, I spent weeks on this but failed. Tools must be easy to use not to keep us from working!

@optimux
Copy link

optimux commented Dec 4, 2022

Hi guys,
I just ran into a wired issue: <error reading variable: failed to get range bounds>. For variables of size 1 in local subroutines or shared from other modules, I can print its value; whereas for variables of size >1 (like 2D arrays or 1D vector), either in local subroutines or from shared modules, it says error reading variable: failed to get range bounds when I tried to print. Do you guys have any ideas? This is quite annoying.

info: macOS Monterey 12.0.1 + gdb 12.1 + intel chip + fortran90

The same code works properly on CentOS9 + gdb 10.2.

Thanks!

@phil-blain
Copy link

phil-blain commented Dec 4, 2022

Hi @optimux, this looks like a general regression in GDB, not specific to macOS. If you can replicate it (using the same GDB version) on Linux, then I encourage you to report it to the GDB bug tracker, see:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment