Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't lldb forward my environment variable anymore?

Tags:

c

xcode

lldb

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.

like image 471
Cornstalks Avatar asked Nov 07 '15 19:11

Cornstalks


People also ask

How do I enable Environment Variables?

On the Windows taskbar, right-click the Windows icon and select System. In the Settings window, under Related Settings, click Advanced system settings. On the Advanced tab, click Environment Variables. Click New to create a new environment variable.

How do I set an environment variable in export?

To set an environment variable, use the command " export varname=value ", which sets the variable and exports it to the global environment (available to other processes). Enclosed the value with double quotes if it contains spaces. To set a local variable, use the command " varname =value " (or " set varname =value ").

How do I set global Environment Variables?

Search and select System (Control Panel). Click on the Advanced system settings link and then click Environment Variables. Under the section System Variables, select the environment variable you want to edit, and click Edit. If the environment variable you want doesn't exist, click New.

Can Environment Variables change during execution?

No. This is not possible. One process can never directly manipulate the environment of a different already-running process.


1 Answers

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.

like image 89
Ken Thomases Avatar answered Sep 17 '22 16:09

Ken Thomases