incedo / fabricate

Automatically exported from code.google.com/p/fabricate
0 stars 0 forks source link

OSX support with DYLD_INSERT_LIBRARIES/interposing #26

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
While OSX has dtruss which has similar output to strace, it (and anything else 
using DTrace) requires root access making it impractical.  Here is an 
alternative implementation using DYLD_INSERT_LIBRARIES, similar to LD_PRELOAD 
on Linux, to detect what files are being accessed.  This requires bundling C 
code into fabricate.py, but seems to work correctly and quickly (probably 
faster than strace as it doesn't need to use regular expressions).

Original issue reported on code.google.com by comexk@gmail.com on 15 Jul 2010 at 1:09

Attachments:

GoogleCodeExporter commented 9 years ago
Improved version that handles more cases.

Original comment by comexk@gmail.com on 25 Jul 2010 at 6:13

Attachments:

GoogleCodeExporter commented 9 years ago
Hi comexk. Nice work. I have been trying to contact you about these patches 
before accepting them. Please email me.  My address is at: 
http://brush.co.nz/contact  -- Berwyn

Original comment by berh...@gmail.com on 27 Jul 2010 at 10:02

GoogleCodeExporter commented 9 years ago
I would like to apply this patch to fabricate to support strace like 
functionality on OSX. The problem I have is that I don't have access to an OSX 
system to test on.

Are there any volunteers to test the patch on OSX. Failing that, are there any 
OSX machines that I could remote access, or be donated to developing this 
patch? Something like http://virtualmacosx.com/ that is free would be a 
solution if any one knows of one. Maybe an unused licence for OSX could be 
donated so I could install it as a virtual machine on my windows box.

Any other suggestions are welcome.

Original comment by simon.al...@gmail.com on 3 May 2013 at 11:25

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
As is, the patch doesn't seem to work. Because of the condition:

    self.parallel_ok = parallel_ok and is_strace and _pool is not None

The build always runs serially. When the 'is_strace' predicate is loosened to 
allow the interposing runner, the script hangs on my input. I'll try to put 
together a minimal reproduction case.

Original comment by jaros...@gmail.com on 20 Jun 2013 at 6:13

GoogleCodeExporter commented 9 years ago
Inside of '_results_handler' in the second for-loop, there is a test of the 
form:

    if still_to_do == 0:
        if isinstance(a.do, _todo):

If the predicate is updated to:

    if still_to_do == 0 or not no_error:

This will prevent hangs on OS X.

Original comment by jaros...@gmail.com on 20 Jun 2013 at 7:37

GoogleCodeExporter commented 9 years ago
On further debug I've ascertained that the dependency file is not being 
properly generated. I don't know if this is an issue with the Interposer, or 
what. I will continue to dig in.

Original comment by jaros...@gmail.com on 20 Jun 2013 at 8:08

GoogleCodeExporter commented 9 years ago
The 'dirs' option was not being set. Whole thing works with the following two 
changes. The first change allows the interposer to run in parallel mode. The 
second change allows scripts to be built using fabricate.py as a 
pseudo-library. (Obviously that is a hack, but it gets the job done, for now.)

@@ -1153,7 +1152,8 @@ class Builder(object):
             self.runner = SmartRunner(self)

         is_strace = isinstance(self.runner.actual_runner(), StraceRunner)
-        self.parallel_ok = parallel_ok and is_strace and _pool is not None
+        is_interpose = isinstance(self.runner.actual_runner(), 
InterposingRunner)
+        self.parallel_ok = parallel_ok and (is_strace or is_interpose) and 
_pool is not None
         if self.parallel_ok:
             global _results
             _results = threading.Thread(target=_results_handler,
@@ -1696,7 +1696,7 @@ def main(globals_dict=None, build_dir=None, 
extra_options=None, builder=None,
         if not options.quiet and os.path.abspath(build_dir) != original_path:
             print "Leaving directory '%s' back to '%s'" % (build_dir, original_path)
         os.chdir(original_path)
-    sys.exit(status)
+    return status

Original comment by jaros...@gmail.com on 20 Jun 2013 at 8:21

GoogleCodeExporter commented 9 years ago
Great job with this patch, thanks folks.

Working for me without too much effort in OSX 10.9, running in VirtualBox, on a 
non-parallel build (haven't tried parallel building).

I had one problem. During a link command, with one of the last object files 
that had a fairly long path name, the line for it in the Interposer's output 
got split up like this (being caught by an assertion when Fabricate tried to 
read it in at the end):

[lots of !read.open... lines]
!read.open /Volumes/[bunch more 
subpaths]/debug/text_old_fontRenderers_F!read.open /Volumes/[bunch more 
subpaths]/debug/libDanDebug.a
!write.open /Volumes/[bunch more subpaths]/debug/libDanDebug.a
!read.stat /Volumes/[bunch more subpaths]/debug/libDanDebug.a
!write.open /Volumes/[bunch more subpaths]/debug/libDanDebug.a
romGlTextureFontToGlSurface.o
[a handful more !read.open... lines]

So, the info about the linker's file writing sort of jumping in there before 
all the info about its file reading had finished printing out. (Again, I should 
note that this wasn't a parallel build). I added "fflush(outfp);" after each 
fprintf to outfp in the Interposer code and that fixed it, moving all the 
libDanDebug.a stuff in that example down to the bottom under all of the 
!read.open lines.

Original comment by daniel.l...@gmail.com on 4 Nov 2014 at 12:46