21

I'm working on a patch for FFmpeg and need to debug my code. I'm loading an external library, and in order to test different library versions, I have them in different folders. To select which one I want to use, I've been using DYLD_LIBRARY_PATH=/path/to/lib/dir ./ffmpeg and that works okay. But when I try it within lldb, it crashes saying dyld: Library not loaded and Reason: image not found. This used to work pre-Xcode 7.1, but I just recently upgraded and it stopped working.


Here's my MVCE:

#include <stdio.h>
#include <stdlib.h>

int main() {
  char* str = getenv("DYLD_LIBRARY_PATH");
  if (str) puts(str);
  else     puts("(null)");
  return 0;
}

Running this program as follows produces the output:

$ ./a.out
(null)
$ DYLD_LIBRARY_PATH=/tmp ./a.out
/tmp

That looks okay. But when I try to use lldb it fails:

$ DYLD_LIBRARY_PATH=/tmp lldb ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) run
Process 54255 launched: './a.out' (x86_64)
(null)
Process 54255 exited with status = 0 (0x00000000)

Trying to set the environment variable inside lldb works:

lldb ./a.out
(lldb) target create "./a.out"
Current executable set to './a.out' (x86_64).
(lldb) env DYLD_LIBRARY_PATH=/tmp
(lldb) run
Process 54331 launched: './a.out' (x86_64)
/tmp
Process 54331 exited with status = 0 (0x00000000) 

lldb version (it's from Xcode 7.1):

$ lldb --version
lldb-340.4.110

Question: Is this an intended new "feature," or is this a new bug in lldb (or am I totally crazy and this never used to work)? I'm quite positive lldb used to forward the DYLD_LIBRARY_PATH environment variable, so how come it isn't anymore?


Edit: This is on OS X 10.11.1.

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • 2
    Confirmed [here](https://www.mail-archive.com/lldb-dev@lists.llvm.org/msg00779.html) by Jason Molenda (who seems to be one of the lldb developers). – Martin R Nov 07 '15 at 20:12

2 Answers2

41

If this is on El Capitan (OS X 10.11), then it's almost certainly a side effect of System Integrity Protection. From the System Integrity Protection Guide: Runtime Protections article:

When a process is started, the kernel checks to see whether the main executable is protected on disk or is signed with an special system entitlement. If either is true, then a flag is set to denote that it is protected against modification. …

… Any dynamic linker (dyld) environment variables, such as DYLD_LIBRARY_PATH, are purged when launching protected processes.

Everything in /usr/bin is protected in this fashion. Therefore, when you invoke /usr/bin/lldb, all DYLD_* environment variables are purged.

It should work to run lldb from within Xcode.app or the Command Line Tools, like so:

DYLD_LIBRARY_PATH=whatever /Applications/Xcode.app/Contents/Developer/usr/bin/lldb <whatever else>

I don't believe that copy of lldb is protected. /usr/bin/lldb is actually just a trampoline that executes the version in Xcode or the Command Line Tools, so you're ultimately running the same thing. But /usr/bin/lldb is protected so the DYLD_* environment variables are purged when running that.

Otherwise, you will have to set the environment variable inside lldb as shown in this thread:

(lldb) process launch --environment DYLD_LIBRARY_PATH=<mydylibpath> -- arg1 arg2 arg3

or using the short -v option:

(lldb) process launch -v DYLD_LIBRARY_PATH=<mydylibpath> -- arg1 arg2 arg3

Or, you can disable System Integrity Protection, although it serves a good purpose.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Yeah, this is on OS X 10.11.1. That's interesting. Thanks for the clear explanation! – Cornstalks Nov 08 '15 at 01:48
  • 2
    Thanks. This solves my problem too (on El Capitan). I've created an alias `alias lldb=/Applications/Xcode.app/Contents/Developer/usr/bin/lldb` to alleviate the typing. – Tzunghsing David Wong Oct 14 '16 at 02:54
  • But I have sip disabled and I still have this issue. Weird. Damn I should have set up gdb instead, it's another one of those appley nonsense I guess – MuhsinFatih Oct 09 '18 at 19:04
  • @MuhsinFatih Does invoking `lldb` using one of the other techniques work? – Ken Thomases Oct 09 '18 at 23:06
  • @KenThomases I am currently getting `Unable to find Mach task port for process-id 57838: (os/kern) failure`. I codesigned gdb but it still doesnt work, I am so pissed off right now. I will try to fix this. Look at this: https://opensource.apple.com/source/lldb/lldb-69/docs/code-signing.txt . It says "probably because of a bug how Keychain Access makes certificates" and this doc is from snowleopard times and it is still not patched. goddamit my assignment is late because of apple bs. There is always something apple has done that ruins my time, always. sorry for rant it just made me feel better – MuhsinFatih Oct 10 '18 at 01:31
  • btw that doc is for lldb but here it says it should fix for gdb as well: https://stackoverflow.com/a/15512279/2770195 – MuhsinFatih Oct 10 '18 at 01:35
  • 1
    For whatever reason, setting the environment variable `process launch -v` doesn’t work for me either on lldb-1001.0.12.1/macOS 10.14.5. Instead I have to do explicitly set the environment via `env` before launching the process. Then it works. – Konrad Rudolph Jul 16 '19 at 10:15
  • In recent versions, LLDB seems to have moved to `/Library/Developer/CommandLineTools/usr/bin/lldb`. – Elliott Slaughter Jul 29 '22 at 22:21
0

You can set an environment variable inside lldb once it is started.

$ lldb
(lldb) help env
Shorthand for viewing and setting environment variables.  Expects 'raw' input (see 'help raw-input'.)

Syntax: 
_regexp-env                  // Show environment
_regexp-env <name>=<value>   // Set an environment variable

'env' is an abbreviation for '_regexp-env'
(lldb) 

So that

lldb ./a.out
(lldb) env DYLD_LIBRARY_PATH=/path/to/lib/dir
(lldb) r

should work. Tested with

$ lldb --version
lldb-1400.0.38.17
Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
user1551605
  • 166
  • 9