Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Debugging using system calls in Mac OS X (bryce.is)
121 points by bryceneal on July 30, 2016 | hide | past | favorite | 22 comments


One thing that the article does not mention is that dtruss is also just a DTrace script (well, a DTrace script in a shell script ;)). DTrace comes with some other nice scripts (iosnoop, execsnoop, opensnoop, etc.)[1].

But you need to disable some portion of the system integrity protection:

http://stackoverflow.com/a/34616033

[1] http://dtrace.org/blogs/brendan/2011/10/10/top-10-dtrace-scr...


I love articles about expert sleuthing, especially when it involves low-level code. I hope the author shares his discovery with the Go engineering and documentation teams, perhaps via bug reports.


If you're into that there's a whole conference on dtrace you should check out called dtrace.conf


Meanwhile, if you try to run the system lldb on the system ruby interpreter on OSX, you get this:

  % lldb ruby
  (lldb) target create "ruby"
  Current executable set to 'ruby' (x86_64).
  (lldb) run
  error: process exited with status -1 
  (cannot attach to process due to System Integrity Protection)


Reboot in safe mode (⌘+R immediately after booting), open a terminal, run:

  csrutil disable
Reboot.

  -> % lldb ruby 
  (lldb) target create "ruby"
  Current executable set to 'ruby' (x86_64).
  (lldb) run
  Process 436 launched: '/usr/bin/ruby' (x86_64)
I for one am glad that it's now much harder to scam my grandparents.


That disables a lot of useful protections, seems overkill just to be able to trace a ruby script :-/


You can also disable just the relevant bits - `csrutil enable --without debug` would probably do the trick here.


In that case, you should probably just not use the system ruby.


And this is why I won't ever switch to OS X full time, and I'll stay with Linux for all my systems level programming. The low level tools just aren't there. With Linux, I've got gdb, objdump, strace, what have you. I'd have to compile most systems level tools from source on Apple laptop.

It's great for app developers, but I mainly do systems level things for personal projects, and I don't want to have to compile _tools_ from scratch. The hardware is awesome and I love the shiny box and the sleek design. I've been using a macbook pro all summer, and the only thing that I'm sold on is the hardware design / case. The charger is nice too.


What's with the tone here? You sound pretty angry while making an argument that largely boils down to "different tools are better for different use cases".


[flagged]


Then maybe you're not qualified to make such judgements?


But you already said you understand the utility for some people. That's the glory. Yours is a use case that's probably that of fewer than 0.1% of people who own Macs.


cp /usr/bin/ruby ~/Desktop/ruby

lldb ~/Desktop/ruby

:-)


cp `which ruby` ~ ; lldb ~/ruby


Great tools, I should try to use them.

In this case could it have been done by lsof ?


"UDP connections"? UPD is connection less.


It is possible to have a "connected UDP socket". It is one that is already set up with a remote endpoint.

if you connect() a SOCK_DGRAM UDP socket to a remote host, you can use send() and recv() as well as sendto() and recvfrom(). If you want.

http://beej.us/guide/bgnet/output/html/multipage/connectman....


UDP certainly is connectionless, but that doesn't mean a host can't call `connect` on a UDP scoket. In fact, it is encouraged[1]. I am going to quote the entire paragraph from the RFC, the guidelines document is a very good read if you plan to use UDP.

Succinctly, you should `connect` a UDP socket, it can simplify some calls and allows the application to receive ICMP errors

    Many operating systems also allow a UDP socket to be connected, i.e., to bind a
    UDP socket to a specific pair of addresses and ports.  This is similar to the
    corresponding TCP sockets API functionality.  However, for UDP, this is only a
    local operation that serves to simplify the local send/receive functions and to
    filter the traffic for the specified addresses and ports.  Binding a UDP socket
    does not establish a connection -- UDP does not notify the remote end when a
    local UDP socket is bound.  Binding a socket also allows configuring options
    that affect the UDP or IP layers, for example, use of the UDP checksum or the
    IP Timestamp option.  On some stacks, a bound socket also allows an application
    to be notified when ICMP error messages are received for its transmissions
    [RFC1122].
[1]: https://tools.ietf.org/html/rfc5405#section-3.6



There's still a lot of state (mostly in firewalls) associated with UDP traffic, and treating it as a connection (even if it isn't technically) can be useful.


You are right. I believe the "connection" analog exists in Go as a means of implementing a common interface across protocols.


I often wonder why I don't come across bugs like this but then I think to myself "I'd never write code that closes a socket until all writes and reads are done."

So the question is: how do you do that in Go?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: