EzDevInfo.com

mach

HTTP for JavaScript

What's the difference between mach_vm_allocate and vm_allocate?

I would like to know what's the difference betweenmach_vm_allocate and vm_allocate. I know mach_vm_allocate is only available in OS X and not iOS, but I'm not sure why. The file that has all the function prototypes in for the mach_vm_... functions (mach/mach_vm.h) only has #error mach_vm.h unsupported. in iOS.


Source: (StackOverflow)

How to get WiFi encryption mode on iOS/iPhone/iPad?

How to get Wi-Fi encryption mode in iOS without private libraries?


Source: (StackOverflow)

Advertisements

Mach exception in iPhone

I sometimes get following exception:

[Mach] exception: 0x%x, count: %d, code: 0x%llx 0x%llx
[Mach] Skipping registered port - it is invalid
[Mach] Skipping registered port - mask does not match
signal %d, info %p, uapVoid %p

I do not have any idea what these exceptions are about. Can somebody throw any light on this?


Source: (StackOverflow)

What is the difference b/w Hurd and Minix

knowing both are micro-kernels, what is the difference b/w Mach(which Hurd based on, as I read) and Minix. are there any architectural difference. a little light over "what is L4" wud be very helpful... I cannot find any documents covering this


Source: (StackOverflow)

Delphi - Obtain Full Stack Trace on OSX

I have an application which can log a stacktrace, which can be later used for debugging.

On Windows, I've gotten by using the excellent JCLDebug unit provided by the JEDI project.

Now that my application is running on OSX, I've hit a bit of a hitch - I don't know how to obtain the correct stacktrace when an exception occurs.

I have got the basics down -

1) I can get a stacktrace using 'backtrace' (found in libSystem.dylib)

2) The resulting backtrace can be converted into line numbers using the .map file provided by Delphi's linker

The issue I'm left with is - I don't know where to call backtrace from. I know that Delphi uses Mach exceptions (on a separate thread), and that I cannot use posix signals, but that's all that I've managed to sort out.

I can get a backtrace in the 'try...except' block, but unfortunately, by that point the stack has already wound down.

How can I install a proper exception logger which will run right after the exception occurs?

Update:

As per 'Honza R's suggestion, I've taken a look at the 'GetExceptionStackInfoProc' procedure.

This function does get me 'inside' of the exception handling process, but unfortunately leaves me with some of the same issues I had previously.

First of all - on desktop platforms, this function 'GetExceptionStackInfoProc' is just a function pointer, which you can assign with your own exception info handler. So out of the box, Delphi doesn't provide any stack information provider.

If I assign a function to 'GetExceptionStackInfoProc' and then run a 'backtrace' inside of it, I receive a stacktrace, but that trace is relative to the exception handler, not the thread which caused the exception.

'GetExceptionStackInfoProc' does contain a pointer to a 'TExceptionRecord', but there's very limited documentation available on this.

I might be going beyond my depth, but how can I get a stacktrace from the correct thread? Would it be possible for me to inject my own 'backtrace' function into the exception handler and then return to the standard exception handler from there?

Update 2

Some more details. One thing to clear up - this question is about exceptions that are handled by MACH messages, not software exceptions that are handled entirely within the RTL.

Embarcadero has laid out some comments along with these functions -

    System.Internal.MachExceptions.pas -> catch_exception_raise_state_identity

    {
     Now we set up the thread state for the faulting thread so that when we
     return, control will be passed to the exception dispatcher on that thread,
     and this POSIX thread will continue watching for Mach exception messages.
     See the documentation at <code>DispatchMachException()</code> for more
     detail on the parameters loaded in EAX, EDX, and ECX.
    }

    System.Internal.ExcUtils.pas -> SignalConverter

    {
      Here's the tricky part.  We arrived here directly by virtue of our
      signal handler tweaking the execution context with our address.  That
      means there's no return address on the stack.  The unwinder needs to
      have a return address so that it can unwind past this function when
      we raise the Delphi exception.  We will use the faulting instruction
      pointer as a fake return address.  Because of the fencepost conditions
      in the Delphi unwinder, we need to have an address that is strictly
      greater than the actual faulting instruction, so we increment that
      address by one.  This may be in the middle of an instruction, but we
      don't care, because we will never be returning to that address.
      Finally, the way that we get this address onto the stack is important.
      The compiler will generate unwind information for SignalConverter that
      will attempt to undo any stack modifications that are made by this
      function when unwinding past it.  In this particular case, we don't want
      that to happen, so we use some assembly language tricks to get around
      the compiler noticing the stack modification.
    }

Which seem to be responsible for the issue I'm having.

When I do a stacktrace after this exception system has handed control over to the RTL, it looks like this - (bearing in mind, the stack unwinder has been superseded by a backtrace routine. The backtrace will hand control over to the unwinder once it is completed)

0: MyExceptionBacktracer
1: initunwinder in System.pas
2: RaiseSignalException in System.Internal.ExcUtils.pas 

Since RaiseSignalException is called by SignalConverter, I'm led to believe that the backtrace function provided by libc is not compatible with the modifications made to the stack. So, it's incapable of reading the stack beyond that point, but the stack is still present underneath.

Does anyone know what to do about that (or whether my hypothesis is correct)?

Update 3

I've finally managed to get proper stacktraces on OSX. Huge thanks to both Honza and Sebastian. By combining both of their techniques, I found something that works.

For anyone else who could benefit from this, here's the basic source. Bear in mind that I'm not quite sure if it's 100% correct, if you can suggest improvements, go ahead. This technique hooks onto an exception right before Delphi unwinds the stack on the faulting thread, and compensates for any stack frame corruption that might have taken place beforehand.

unit MyExceptionHandler;

interface

implementation

uses
  SysUtils;

var
  PrevRaiseException: function(Exc: Pointer): LongBool; cdecl;

function backtrace2(base : NativeUInt; buffer : PPointer; size : Integer) : Integer;
var SPMin   : NativeUInt;
begin
  SPMin:=base;
  Result:=0;
  while (size > 0) and (base >= SPMin) and (base <> 0) do begin

    buffer^:=PPointer(base + 4)^;
    base:=PNativeInt(base)^;

    //uncomment to test stacktrace
    //WriteLn(inttohex(NativeUInt(buffer^), 8));

    Inc(Result);
    Inc(buffer);
    Dec(size);

  end;
  if (size > 0) then buffer^:=nil;
end;

procedure UnInstallExceptionHandler; forward;

var
  InRaiseException: Boolean;

function RaiseException(Exc: Pointer): LongBool; cdecl;
var b : NativeUInt;
    c : Integer;
    buff : array[0..7] of Pointer;
begin
  InRaiseException := True;

  asm
    mov b, ebp
  end;

  c:=backtrace2(b - $4 {this is the compiler dependent value}, @buff, Length(buff));
  //... do whatever you want to do with the stacktrace

  Result := PrevRaiseException(Exc);
  InRaiseException := False;
end;

procedure InstallExceptionHandler;
var
  U: TUnwinder;
begin
  GetUnwinder(U);
  Assert(Assigned(U.RaiseException));
  PrevRaiseException := U.RaiseException;
  U.RaiseException := RaiseException;
  SetUnwinder(U);
end;

procedure UnInstallExceptionHandler;
var
  U: TUnwinder;
begin
  GetUnwinder(U);
  U.RaiseException := PrevRaiseException;
  SetUnwinder(U);
end;

initialization
  InstallExceptionHandler;
end.

Source: (StackOverflow)

Total RAM in iPhone

I want to know the Total RAM available in my iPhone. For this I've used the following code.

Note: Please do not interpret the question as to retrieve RAM statistics such as Wired, Inactive, Active and Free.

mach_port_t host_port;  
    mach_msg_type_number_t host_size;  
    vm_size_t pagesize;  
    host_port = mach_host_self();  
    host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);  
    host_page_size(host_port, &pagesize);  
    vm_statistics_data_t vm_stat;  
    if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {  
        NSLog(@"Failed to fetch vm statistics");  
        return;  
    }    

    /* Stats in bytes */  
    self.wired = vm_stat.wire_count * pagesize / (1024 * 1024);
    self.active = vm_stat.active_count * pagesize / (1024 * 1024);
    self.inactive = vm_stat.inactive_count * pagesize / (1024 * 1024);
    self.free = vm_stat.free_count * pagesize / (1024 * 1024);
    self.used = self.active + self.inactive + self.wired;
    self.total = self.used + self.free;

Here are the results:

  • Simulator: total memory = 2045 (my PC contains 2GB RAM). Seems correct.
  • Device (iPhone 4): total memory = 390 (should be 512). Incorrect.
  • Device (iPhone 3GS): total memory = 84 (should be 256). Incorrect.

Please let me know if this is the correct way to calculate the TOTAL RAM of an iDevice?


Source: (StackOverflow)

How do I recover from EXC_BAD_ACCESS?

I'm intentionally causing an EXC_BAD_ACCESS. By triggering a write to an NSObject in a read-only virtual memory page. Ideally, I'd like to catch EXC_BAD_ACCESS, mark the virtual memory page as read-write and have execution continue as it normally would have. Is this even possible? The code I've written to cause the EXC_BAD_ACCESS is below.

WeakTargetObject.h (ARC)

@interface WeakTargetObject : NSObject
@property (nonatomic, weak) NSObject *target;
@end

WeakTargetObject.m (ARC)

@implementation WeakTargetObject
@end

main.m (MRR)

- (void)main {
  char *mem = NULL;
  vm_allocate(mach_task_self(), (vm_address_t *)&mem, vm_page_size, VM_FLAGS_ANYWHERE);
  NSLog(@"mem: %p", mem);
  WeakTargetObject *weakTargetObject = objc_constructInstance([WeakTargetObject class], (void *)mem);

  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSObject *target = [[NSObject alloc] init];
  weakTargetObject.target = target;
  [pool drain];
  pool = [[NSAutoreleasePool alloc] init];
  NSLog(@"expect non-nil. weakTargetObject.target: %@", weakTargetObject.target);
  [pool drain];

  vm_protect(mach_task_self(),
             (vm_address_t)mem,
             vm_page_size,
             1,
             VM_PROT_READ);

  // triggers EXC_BAD_ACCESS when objc runtime 
  // tries to nil weakTargetObject.target
  [weakTargetObject release]; 
  NSLog(@"expect nil. weakTargetObject.target: %@", weakTargetObject.target);
}

Source: (StackOverflow)

Why is it prohivited to use fork without exec in mac?

My question is quite simple. On Linux it is quite popular to use fork without exec

However, I have found that on MacOS this is not possible (see fork manual)

https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fork.2.html

There are limits to what you can do in the child process. To be totally safe you should restrict your-self yourself self to only executing async-signal safe operations until such time as one of the exec functions is called. All APIs, including global data symbols, in any framework or library should be assumed to be unsafe after a fork() unless explicitly documented to be safe or async-signal safe. If you need to use these frameworks in the child process, you must exec. In this situation it is reasonable to exec yourself.

This seems strange to me? What is the reason? Is it possible to workaround it?


Source: (StackOverflow)

Sharing Mach ports with child processes

I am doing a comparison of different IPC mechanisms available on Mac OS X (pipes, sockets, System V IPC, etc.), and I would like to see how Mach ports compare to the higher-level alternatives. However, I've run into a very basic issue: getting send rights to ports across processes (specifically, across a parent process and a child process).

Unlike file descriptors, ports are generally not carried over to forked processes. This means that some other way to transfer them must be established. Just about the only relevant page I could find about this was this one, and they state in an update that their method no longer works and never was guaranteed to, even though that method was suggested by an Apple engineer in 2009. (It implied replacing the bootstrap port, and now doing that breaks XPC.) The replacement they suggest uses deprecated functions, so that's not a very appealing solution.

Besides, one thing I liked about the old solution is that ports remained pretty much private between the processes that used it. There was no need to broadcast the existence of the port, just like pipes (from the pipe call) work once forked. (I'll probably live with it if there's another solution, but it's a little annoying.)

So, how do you pass a send right to a Mach port from a parent process to a child process?


Source: (StackOverflow)

Porting a kernel to a different architecture?

I want to port the xnu kernel to the ARM architecture, with the ultimate goal of being able to run a full kernel inside Qemu. While I do realise that this is a very difficult task, I still want to have a go at it.

As far as I know, you're meant to write an entry point for the kernel (osfmk/arm/start.s) where you do general initialisation (MMU and PlatformExpert) after which the Kext/IOKit subsystems can be started and load CPU specific extensions (ie. traps, GPIO, clock) which are either prelinked into the binary or loaded by the bootloader (because the kernel can't interact with the filesystem due to the NAND extensions not being available yet).

While I do have a general idea on how ARM CPUs work, I don't even know where to get started with the xnu port, because I'm not entirely sure how to:

  • Do low level debugging (since the kernel debugging facilities are unavailable early during startup).
  • Integrate the ARM branch with the rest of the kernel source tree (ie. making sure the stuff in osfmk/kern is working).
  • Create a sane environment for platform independent kernel to start (machine_startup());
  • Fix up some platform specific code inside the main kernel code (most of the platform code is limited to osfmk/platform_name but some of it has to be integrated into osfmk/kern and others).

Are there any decent guides on porting the XNU (or at least Mach) kernel to different platforms, just like there are Linux guides?


Source: (StackOverflow)

GoLang / CGO: Problems calling Mach API host_statistics() from Go

I use the following C code fragment to get the CPU load on OS X:

    #include <mach/message.h> 
    #include <mach/mach_host.h>
    #include <mach/host_info.h>

    [...]

    mach_msg_type_number_t  count = HOST_CPU_LOAD_INFO_COUNT;
    kern_return_t error;
    host_cpu_load_info_data_t r_load;

    mach_port_t host_port = mach_host_self();
    error = host_statistics(host_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count);

I have tried to port this piece of code to Go after reading the cgo tutorial. The resulting code looks like this:

package main

/*
#include <stdlib.h>
#include <mach/message.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
*/
import "C"

func main() {
    var err C.kern_return_t
    var host_info_out C.host_info_t
    var host_port C.mach_port_t = C.mach_host_self()

    count := C.mach_msg_type_number_t(C.HOST_CPU_LOAD_INFO_COUNT)

    err = C.host_statistics(C.host_t(host_port), C.HOST_CPU_LOAD_INFO, &host_info_out, &count)
}

However, when I try to build the code, I end up with the following error message

go build cputimes.go 
# command-line-arguments
cputimes.go:33: cannot use &host_info_out (type *_Ctype_host_info_t) as type *_Ctype_integer_t in function argument

I do not udnerstand why cgo complains about the type. The signature of host_statistics() is defined in the mach headers as:

 kern_return_t host_statistics
 (
      host_t host_priv,
      host_flavor_t flavor,
      host_info_t host_info_out,
      mach_msg_type_number_t *host_info_outCnt
 );

Source: (StackOverflow)

Best way to communicate from KEXT to Daemon and block until result is returned from Daemon

In KEXT, I am listening for file close via vnode or file scope listener. For certain (very few) files, I need to send file path to my system daemon which does some processing (this has to happen in daemon) and returns the result back to KEXT. The file close call needs to be blocked until I get response from daemon. Based on result I need to some operation in close call and return close call successfully. There is lot of discussion on KEXT communication related topic on the forum. But they are not conclusive and appears be very old (year 2002 around). This requirement can be handled by FtlSendMessage(...) Win32 API. I am looking for equivalent of that on Mac

Here is what I have looked at and want to summarize my understanding:

  1. Mach message: Provides very good way of bidirectional communication using sender and reply ports with queueing mechansim. However, the mach message APIs (e.g. mach_msg, mach_port_allocate, bootstrap_look_up) don't appear to be KPIs. The mach API mach_msg_send_from_kernel can be used, but that alone will not help in bidirectional communication. Is my understanding right?
  2. IOUserClient: This appears be more to do with communicating from User space to KEXT and then having some callbacks from KEXT. I did not find a way to initiate communication from KEXT to daemon and then wait for result from daemon. Am I missing something?
  3. Sockets: This could be last option since I would have to implement entire bidirectional communication channel from KEXT to Daemon.
  4. ioctl/sysctl: I don't know much about them. From what I have read, its not recommended option especially for bidirectional communication
  5. RPC-Mig: Again I don't know much about them. Looks complicated from what I have seen. Not sure if this is recommended way.
  6. KUNCUserNotification: This appears to be just providing notification to the user from KEXT. It does not meet my requirement.

Supported platform is (10.5 onwards). So looking at the requirement, can someone suggest and provide some pointers on this topic?

Thanks in advance.


Source: (StackOverflow)

Which PID listens on a given mach port

My application recieves mach IPC messages and return answers for the callers. I have mach caller port(msgh_remote_port) and I want to know PID of the caller. Can I find on OSX by the mach port a PID wich listen for specific mach port?


Source: (StackOverflow)

Is there a way to unload bundle after mach_inject

I want to load the newer version of bundle to the target process but it's impossible because the bundle with same name already loaded. Changing CFBundleVersion or CFBundleShortVersionString of bundle doesn't work. The easiest way to do it is simply kill the target process and restart it. But I don't think that it's a best way to do it. So is there another way to do it?


Source: (StackOverflow)

Why does host_statistics64() return inconsistent results?

Why does host_statistics64() in OS X 10.6.8 (I don't know if other versions have this problem) return counts for free, active, inactive, and wired memory that don't add up to the total amount of ram? And why is it missing an inconsistent number of pages?

The following output represents the number of pages not classified as free, active, inactive, or wired over ten seconds (sampled roughly once per second).

458
243
153
199
357
140
304
93
181
224

The code that produces the numbers above is:

#include <stdio.h>
#include <mach/mach.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <unistd.h>

int main(int argc, char** argv) {
        struct vm_statistics64 stats;
        mach_port_t host = mach_host_self();
        natural_t count = HOST_VM_INFO64_COUNT;
        natural_t missing = 0;
        kern_return_t ret;
        int mib[2];
        long ram;
        natural_t pages;
        size_t length;
        int i;

        mib[0] = CTL_HW;
        mib[1] = HW_MEMSIZE;
        length = sizeof(long);
        sysctl(mib, 2, &ram, &length, NULL, 0);
        pages = ram / getpagesize();

        for (i = 0; i < 10 i++) {
                if ((ret = host_statistics64(host, HOST_VM_INFO64, (host_info64_
t)&stats, &count)) != KERN_SUCCESS) {
                        printf("oops\n");
                }

                missing = pages - (stats.free_count + stats.active_count + stats
.inactive_count + stats.wire_count);

                printf("%i\n", missing);
                sleep(1);
        }

        return 0;
}

Source: (StackOverflow)