mach
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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:
- 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?
- 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?
- Sockets: This could be last option since I would have to implement entire bidirectional communication channel from KEXT to Daemon.
ioct
l/sysctl
: I don't know much about them. From what I have read, its not recommended option especially for bidirectional communication
- RPC-Mig: Again I don't know much about them. Looks complicated from what I have seen. Not sure if this is recommended way.
- 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)
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)
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() 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)