LLDB Cannot Load ODBC Driver Due to Sandbox Restrictions - How to Debug

I'm developing a macOS console application that uses ODBC to connect to PostgreSQL. The application works fine when run normally, but fails to load the ODBC driver when debugging with LLDB(under root works fine as well).

Error Details When running the application through LLDB, I get this sandbox denial in the system log (via log stream): Error 0x0 0 0 kernel: (Sandbox) Sandbox: logd_helper(587) deny(1) file-read-data /opt/homebrew/lib/psqlodbcw.so The application cannot access the PostgreSQL ODBC driver located at /opt/homebrew/lib/psqlodbcw.so(also tried copy to /usr/local/lib/...). Environment

macOS Version: Latest Sequoia LLDB: Using LLDB from Xcode 16.3 (/Applications/Xcode16.3.app/Contents/Developer/usr/bin/lldb) ODBC Driver: PostgreSQL ODBC driver installed via Homebrew Code Signing: Application is signed with Apple Development certificate

What is the recommended approach for debugging applications that need to load dynamic libraries? Are there specific entitlements or configurations that would allow LLDB to access ODBC drivers during debugging sessions?

Any guidance would be greatly appreciated. Thank you for any assistance!

Answered by DTS Engineer in 857973022
I'm developing a macOS console application

“Console application” isn’t a term we use on Apple platforms. An application is, by definition, something the user double clicks in the Finder, shows up in the Dock, has a menu bar, and so on. I’m presuming that you’re building a command-line tool, something that the user runs from Terminal, or is run by the system as, say, a launchd daemon. Please let me know if that’s not the case.

What is the recommended approach for debugging applications that need to load dynamic libraries?

There are a number of factors in play. I’ll come back to that later. But first I want to dig into your log message:

Error Details When running the application through LLDB, I get this sandbox denial in the system log… logd_helper(587)

Look at that message carefully. It originates from a macOS system process, logd_helper. So this is not the case that your program is unable to load this shared library. Rather, it’s that some system process is unable to load this shared library [1]. So, this log message doesn’t indicate a problem with your code.

Note logd_helper has a man page, although it’s not super helpful.

Other than this log message, is there any problem with your code when you run it under LLDB? If not, I’d treat this as log noise.


Coming back to the rule for loading code into your process:

  • If the process is sandboxed, the code must be within the process’s static sandbox. Note that your process is unlikely to be sandboxed because it’s not an app.
  • If the process has library validation enabled, that applies constraints. More on that below.
  • If the process has the hardened runtime enabled, that enables library validation by default. You can opt out of that with an entitlement.
  • If the library is otherwise loadable, it can be blocked by library constraints. See Applying launch environment and library constraints.

Library validation is an important security feature, ensuring that all code you load is either signed by you or signed by Apple. There are reasons you might disable it in a real product - for example, your process supports in-process plug-ins created by a range of third-party developers — but mostly you want to leave it enabled.

Disabling library validation makes it harder to pass notarisation. See Resolving common notarization issues.

Disabling library validation makes it harder to pass Gatekeeper. See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths.

If you’re building a product that you plan to ship to a wide range of users, the correct approach to open source software like this is to bundle the version of the software you need and then re-sign that as your code. OTOH, if this is just a quick hack you’re cobbling together, it’s fine to disable library validation.

Having said that, the error you’re seeing is not related to an issue in your code, so the above is just an FYI.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] As to why that is, my best guess is this is due to a complex chain of events:

  1. Someone has logged some data.
  2. Someone is trying to present that data to the user.
  3. That data is in a custom format.
  4. So the logging subsystem is trying to load a plug-in to render the data. It spawns logd_helper to do this because, sheesh, we don’t want to be loading random code into the logging daemon directly.
  5. Your third-party tooling has installed one of these plug-ins.
  6. And the system can’t load that because logd_helper is sandoxed.

However, that’s just speculation and I’d need to do a lot more research before I can say that definitively.

I'm developing a macOS console application

“Console application” isn’t a term we use on Apple platforms. An application is, by definition, something the user double clicks in the Finder, shows up in the Dock, has a menu bar, and so on. I’m presuming that you’re building a command-line tool, something that the user runs from Terminal, or is run by the system as, say, a launchd daemon. Please let me know if that’s not the case.

What is the recommended approach for debugging applications that need to load dynamic libraries?

There are a number of factors in play. I’ll come back to that later. But first I want to dig into your log message:

Error Details When running the application through LLDB, I get this sandbox denial in the system log… logd_helper(587)

Look at that message carefully. It originates from a macOS system process, logd_helper. So this is not the case that your program is unable to load this shared library. Rather, it’s that some system process is unable to load this shared library [1]. So, this log message doesn’t indicate a problem with your code.

Note logd_helper has a man page, although it’s not super helpful.

Other than this log message, is there any problem with your code when you run it under LLDB? If not, I’d treat this as log noise.


Coming back to the rule for loading code into your process:

  • If the process is sandboxed, the code must be within the process’s static sandbox. Note that your process is unlikely to be sandboxed because it’s not an app.
  • If the process has library validation enabled, that applies constraints. More on that below.
  • If the process has the hardened runtime enabled, that enables library validation by default. You can opt out of that with an entitlement.
  • If the library is otherwise loadable, it can be blocked by library constraints. See Applying launch environment and library constraints.

Library validation is an important security feature, ensuring that all code you load is either signed by you or signed by Apple. There are reasons you might disable it in a real product - for example, your process supports in-process plug-ins created by a range of third-party developers — but mostly you want to leave it enabled.

Disabling library validation makes it harder to pass notarisation. See Resolving common notarization issues.

Disabling library validation makes it harder to pass Gatekeeper. See Resolving Gatekeeper Problems Caused by Dangling Load Command Paths.

If you’re building a product that you plan to ship to a wide range of users, the correct approach to open source software like this is to bundle the version of the software you need and then re-sign that as your code. OTOH, if this is just a quick hack you’re cobbling together, it’s fine to disable library validation.

Having said that, the error you’re seeing is not related to an issue in your code, so the above is just an FYI.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] As to why that is, my best guess is this is due to a complex chain of events:

  1. Someone has logged some data.
  2. Someone is trying to present that data to the user.
  3. That data is in a custom format.
  4. So the logging subsystem is trying to load a plug-in to render the data. It spawns logd_helper to do this because, sheesh, we don’t want to be loading random code into the logging daemon directly.
  5. Your third-party tooling has installed one of these plug-ins.
  6. And the system can’t load that because logd_helper is sandoxed.

However, that’s just speculation and I’d need to do a lot more research before I can say that definitively.

LLDB Cannot Load ODBC Driver Due to Sandbox Restrictions - How to Debug
 
 
Q