VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/darwin/dbgkrnlinfo-r0drv-darwin.cpp@ 62477

Last change on this file since 62477 was 62477, checked in by vboxsync, 8 years ago

(C) 2016

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 40.0 KB
Line 
1/* $Id: dbgkrnlinfo-r0drv-darwin.cpp 62477 2016-07-22 18:27:37Z vboxsync $ */
2/** @file
3 * IPRT - Kernel Debug Information, R0 Driver, Darwin.
4 */
5
6/*
7 * Copyright (C) 2011-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#ifdef IN_RING0
32# include "the-darwin-kernel.h"
33# include <sys/kauth.h>
34RT_C_DECLS_BEGIN /* Buggy 10.4 headers, fixed in 10.5. */
35# include <sys/kpi_mbuf.h>
36# include <net/kpi_interfacefilter.h>
37# include <sys/kpi_socket.h>
38# include <sys/kpi_socketfilter.h>
39RT_C_DECLS_END
40# include <sys/buf.h>
41# include <sys/vm.h>
42# include <sys/vnode_if.h>
43/*# include <sys/sysctl.h>*/
44# include <sys/systm.h>
45# include <vfs/vfs_support.h>
46/*# include <miscfs/specfs/specdev.h>*/
47#else
48# include <stdio.h> /* for printf */
49#endif
50
51#include "internal/iprt.h"
52#include <iprt/dbg.h>
53
54#include <iprt/asm.h>
55#include <iprt/assert.h>
56#include <iprt/err.h>
57#include <iprt/assert.h>
58#include <iprt/file.h>
59#include <iprt/log.h>
60#include <iprt/mem.h>
61#include <iprt/string.h>
62#include <iprt/formats/mach-o.h>
63#include "internal/magics.h"
64
65/** @def MY_CPU_TYPE
66 * The CPU type targeted by the compiler. */
67/** @def MY_CPU_TYPE
68 * The "ALL" CPU subtype targeted by the compiler. */
69/** @def MY_MACHO_HEADER
70 * The Mach-O header targeted by the compiler. */
71/** @def MY_MACHO_MAGIC
72 * The Mach-O header magic we're targeting. */
73/** @def MY_SEGMENT_COMMAND
74 * The segment command targeted by the compiler. */
75/** @def MY_SECTION
76 * The section struture targeted by the compiler. */
77/** @def MY_NLIST
78 * The symbol table entry targeted by the compiler. */
79#ifdef RT_ARCH_X86
80# define MY_CPU_TYPE CPU_TYPE_I386
81# define MY_CPU_SUBTYPE_ALL CPU_SUBTYPE_I386_ALL
82# define MY_MACHO_HEADER mach_header_32_t
83# define MY_MACHO_MAGIC IMAGE_MACHO32_SIGNATURE
84# define MY_SEGMENT_COMMAND segment_command_32_t
85# define MY_SECTION section_32_t
86# define MY_NLIST macho_nlist_32_t
87
88#elif defined(RT_ARCH_AMD64)
89# define MY_CPU_TYPE CPU_TYPE_X86_64
90# define MY_CPU_SUBTYPE_ALL CPU_SUBTYPE_X86_64_ALL
91# define MY_MACHO_HEADER mach_header_64_t
92# define MY_MACHO_MAGIC IMAGE_MACHO64_SIGNATURE
93# define MY_SEGMENT_COMMAND segment_command_64_t
94# define MY_SECTION section_64_t
95# define MY_NLIST macho_nlist_64_t
96
97#else
98# error "Port me!"
99#endif
100
101/** @name Return macros for make it simpler to track down too paranoid code.
102 * @{
103 */
104#ifdef DEBUG
105# define RETURN_VERR_BAD_EXE_FORMAT \
106 do { Assert(!g_fBreakpointOnError); return VERR_BAD_EXE_FORMAT; } while (0)
107# define RETURN_VERR_LDR_UNEXPECTED \
108 do { Assert(!g_fBreakpointOnError); return VERR_LDR_UNEXPECTED; } while (0)
109# define RETURN_VERR_LDR_ARCH_MISMATCH \
110 do { Assert(!g_fBreakpointOnError); return VERR_LDR_ARCH_MISMATCH; } while (0)
111#else
112# define RETURN_VERR_BAD_EXE_FORMAT do { return VERR_BAD_EXE_FORMAT; } while (0)
113# define RETURN_VERR_LDR_UNEXPECTED do { return VERR_LDR_UNEXPECTED; } while (0)
114# define RETURN_VERR_LDR_ARCH_MISMATCH do { return VERR_LDR_ARCH_MISMATCH; } while (0)
115#endif
116/** @} */
117
118#define VERR_LDR_UNEXPECTED (-641)
119
120
121/*********************************************************************************************************************************
122* Structures and Typedefs *
123*********************************************************************************************************************************/
124/**
125 * Our internal representation of the mach_kernel after loading it's symbols
126 * and successfully resolving their addresses.
127 */
128typedef struct RTDBGKRNLINFOINT
129{
130 /** Magic value (RTDBGKRNLINFO_MAGIC). */
131 uint32_t u32Magic;
132 /** Reference counter. */
133 uint32_t volatile cRefs;
134
135 /** @name Result.
136 * @{ */
137 /** Pointer to the string table. */
138 char *pachStrTab;
139 /** The size of the string table. */
140 uint32_t cbStrTab;
141 /** The file offset of the string table. */
142 uint32_t offStrTab;
143 /** Pointer to the symbol table. */
144 MY_NLIST *paSyms;
145 /** The size of the symbol table. */
146 uint32_t cSyms;
147 /** The file offset of the symbol table. */
148 uint32_t offSyms;
149 /** Offset between link address and actual load address. */
150 uintptr_t offLoad;
151 /** @} */
152
153 /** @name Used during loading.
154 * @{ */
155 /** The file handle. */
156 RTFILE hFile;
157 /** The architecture image offset (fat_arch_t::offset). */
158 uint64_t offArch;
159 /** The architecture image size (fat_arch_t::size). */
160 uint32_t cbArch;
161 /** The number of load commands (mach_header_XX_t::ncmds). */
162 uint32_t cLoadCmds;
163 /** The size of the load commands. */
164 uint32_t cbLoadCmds;
165 /** The load commands. */
166 load_command_t *pLoadCmds;
167 /** Section pointer table (points into the load commands). */
168 MY_SECTION const *apSections[MACHO_MAX_SECT];
169 /** The number of sections. */
170 uint32_t cSections;
171 /** @} */
172
173 /** Buffer space. */
174 char abBuf[_4K];
175} RTDBGKRNLINFOINT;
176
177
178/*********************************************************************************************************************************
179* Structures and Typedefs *
180*********************************************************************************************************************************/
181#ifdef DEBUG
182static bool g_fBreakpointOnError = false;
183#endif
184
185
186#ifdef IN_RING0
187
188/** Default file permissions for newly created files. */
189#if defined(S_IRUSR) && defined(S_IWUSR)
190# define RT_FILE_PERMISSION (S_IRUSR | S_IWUSR)
191#else
192# define RT_FILE_PERMISSION (00600)
193#endif
194
195/**
196 * Darwin kernel file handle data.
197 */
198typedef struct RTFILEINT
199{
200 /** Magic value (RTFILE_MAGIC). */
201 uint32_t u32Magic;
202 /** The open mode flags passed to the kernel API. */
203 int fOpenMode;
204 /** The open flags passed to RTFileOpen. */
205 uint64_t fOpen;
206 /** The VFS context in which the file was opened. */
207 vfs_context_t hVfsCtx;
208 /** The vnode returned by vnode_open. */
209 vnode_t hVnode;
210} RTFILEINT;
211/** Magic number for RTFILEINT::u32Magic (To Be Determined). */
212#define RTFILE_MAGIC UINT32_C(0x01020304)
213
214
215RTDECL(int) RTFileOpen(PRTFILE phFile, const char *pszFilename, uint64_t fOpen)
216{
217 RTFILEINT *pThis = (RTFILEINT *)RTMemAllocZ(sizeof(*pThis));
218 if (!pThis)
219 return VERR_NO_MEMORY;
220 IPRT_DARWIN_SAVE_EFL_AC();
221
222 errno_t rc;
223 pThis->u32Magic = RTFILE_MAGIC;
224 pThis->fOpen = fOpen;
225 pThis->hVfsCtx = vfs_context_current();
226 if (pThis->hVfsCtx != NULL)
227 {
228 int fCMode = (fOpen & RTFILE_O_CREATE_MODE_MASK)
229 ? (fOpen & RTFILE_O_CREATE_MODE_MASK) >> RTFILE_O_CREATE_MODE_SHIFT
230 : RT_FILE_PERMISSION;
231 int fVnFlags = 0; /* VNODE_LOOKUP_XXX */
232 int fOpenMode = 0;
233 if (fOpen & RTFILE_O_NON_BLOCK)
234 fOpenMode |= O_NONBLOCK;
235 if (fOpen & RTFILE_O_WRITE_THROUGH)
236 fOpenMode |= O_SYNC;
237
238 /* create/truncate file */
239 switch (fOpen & RTFILE_O_ACTION_MASK)
240 {
241 case RTFILE_O_OPEN: break;
242 case RTFILE_O_OPEN_CREATE: fOpenMode |= O_CREAT; break;
243 case RTFILE_O_CREATE: fOpenMode |= O_CREAT | O_EXCL; break;
244 case RTFILE_O_CREATE_REPLACE: fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */
245 }
246 if (fOpen & RTFILE_O_TRUNCATE)
247 fOpenMode |= O_TRUNC;
248
249 switch (fOpen & RTFILE_O_ACCESS_MASK)
250 {
251 case RTFILE_O_READ:
252 fOpenMode |= FREAD;
253 break;
254 case RTFILE_O_WRITE:
255 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE : FWRITE;
256 break;
257 case RTFILE_O_READWRITE:
258 fOpenMode |= fOpen & RTFILE_O_APPEND ? O_APPEND | FWRITE | FREAD : FWRITE | FREAD;
259 break;
260 default:
261 AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#x\n", fOpen));
262 IPRT_DARWIN_RESTORE_EFL_AC();
263 return VERR_INVALID_PARAMETER;
264 }
265
266 pThis->fOpenMode = fOpenMode;
267 rc = vnode_open(pszFilename, fOpenMode, fCMode, fVnFlags, &pThis->hVnode, pThis->hVfsCtx);
268 if (rc == 0)
269 {
270 *phFile = pThis;
271 IPRT_DARWIN_RESTORE_EFL_AC();
272 return VINF_SUCCESS;
273 }
274
275 rc = RTErrConvertFromErrno(rc);
276 }
277 else
278 rc = VERR_INTERNAL_ERROR_5;
279 RTMemFree(pThis);
280
281 IPRT_DARWIN_RESTORE_EFL_AC();
282 return rc;
283}
284
285
286RTDECL(int) RTFileClose(RTFILE hFile)
287{
288 if (hFile == NIL_RTFILE)
289 return VINF_SUCCESS;
290
291 RTFILEINT *pThis = hFile;
292 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
293 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
294 pThis->u32Magic = ~RTFILE_MAGIC;
295
296 IPRT_DARWIN_SAVE_EFL_AC();
297 errno_t rc = vnode_close(pThis->hVnode, pThis->fOpenMode & (FREAD | FWRITE), pThis->hVfsCtx);
298 IPRT_DARWIN_RESTORE_EFL_AC();
299
300 RTMemFree(pThis);
301 return RTErrConvertFromErrno(rc);
302}
303
304
305RTDECL(int) RTFileReadAt(RTFILE hFile, RTFOFF off, void *pvBuf, size_t cbToRead, size_t *pcbRead)
306{
307 RTFILEINT *pThis = hFile;
308 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
309 AssertReturn(pThis->u32Magic == RTFILE_MAGIC, VERR_INVALID_HANDLE);
310
311 off_t offNative = (off_t)off;
312 AssertReturn((RTFOFF)offNative == off, VERR_OUT_OF_RANGE);
313 IPRT_DARWIN_SAVE_EFL_AC();
314
315#if 0 /* Added in 10.6, grr. */
316 errno_t rc;
317 if (!pcbRead)
318 rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
319 vfs_context_ucred(pThis->hVfsCtx), NULL, vfs_context_proc(pThis->hVfsCtx));
320 else
321 {
322 int cbLeft = 0;
323 rc = vn_rdwr(UIO_READ, pThis->hVnode, (char *)pvBuf, cbToRead, offNative, UIO_SYSSPACE, 0 /*ioflg*/,
324 vfs_context_ucred(pThis->hVfsCtx), &cbLeft, vfs_context_proc(pThis->hVfsCtx));
325 *pcbRead = cbToRead - cbLeft;
326 }
327 IPRT_DARWIN_RESTORE_EFL_AC();
328 return !rc ? VINF_SUCCESS : RTErrConvertFromErrno(rc);
329
330#else
331 uio_t hUio = uio_create(1, offNative, UIO_SYSSPACE, UIO_READ);
332 if (!hUio)
333 {
334 IPRT_DARWIN_RESTORE_EFL_AC();
335 return VERR_NO_MEMORY;
336 }
337 errno_t rc;
338 if (uio_addiov(hUio, (user_addr_t)(uintptr_t)pvBuf, cbToRead) == 0)
339 {
340 rc = VNOP_READ(pThis->hVnode, hUio, 0 /*ioflg*/, pThis->hVfsCtx);
341 if (pcbRead)
342 *pcbRead = cbToRead - uio_resid(hUio);
343 else if (!rc && uio_resid(hUio))
344 rc = VERR_FILE_IO_ERROR;
345 }
346 else
347 rc = VERR_INTERNAL_ERROR_3;
348 uio_free(hUio);
349 IPRT_DARWIN_RESTORE_EFL_AC();
350 return rc;
351
352#endif
353}
354
355#endif
356
357
358/**
359 * Close and free up resources we no longer needs.
360 *
361 * @param pThis The internal scratch data.
362 */
363static void rtR0DbgKrnlDarwinLoadDone(RTDBGKRNLINFOINT *pThis)
364{
365 RTFileClose(pThis->hFile);
366 pThis->hFile = NIL_RTFILE;
367
368 RTMemFree(pThis->pLoadCmds);
369 pThis->pLoadCmds = NULL;
370 memset((void *)&pThis->apSections[0], 0, sizeof(pThis->apSections[0]) * MACHO_MAX_SECT);
371}
372
373
374/**
375 * Looks up a kernel symbol.
376 *
377 * @returns The symbol address on success, 0 on failure.
378 * @param pThis The internal scratch data.
379 * @param pszSymbol The symbol to resolve. Automatically prefixed
380 * with an underscore.
381 */
382static uintptr_t rtR0DbgKrnlDarwinLookup(RTDBGKRNLINFOINT *pThis, const char *pszSymbol)
383{
384 uint32_t const cSyms = pThis->cSyms;
385 MY_NLIST const *pSym = pThis->paSyms;
386
387#if 1
388 /* linear search. */
389 for (uint32_t iSym = 0; iSym < cSyms; iSym++, pSym++)
390 {
391 if (pSym->n_type & MACHO_N_STAB)
392 continue;
393
394 const char *pszTabName= &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
395 if ( *pszTabName == '_'
396 && strcmp(pszTabName + 1, pszSymbol) == 0)
397 return pSym->n_value + pThis->offLoad;
398 }
399#else
400 /** @todo binary search. */
401
402#endif
403 return 0;
404}
405
406
407/* Rainy day: Find the right headers for these symbols ... if there are any. */
408extern "C" void ev_try_lock(void);
409extern "C" void OSMalloc(void);
410extern "C" void OSlibkernInit(void);
411extern "C" void kdp_set_interface(void);
412
413
414/**
415 * Check the symbol table against symbols we known symbols.
416 *
417 * This is done to detect whether the on disk image and the in
418 * memory images matches. Mismatches could stem from user
419 * replacing the default kernel image on disk.
420 *
421 * @returns IPRT status code.
422 * @param pThis The internal scratch data.
423 */
424static int rtR0DbgKrnlDarwinCheckStandardSymbols(RTDBGKRNLINFOINT *pThis)
425{
426 static struct
427 {
428 const char *pszName;
429 uintptr_t uAddr;
430 } const s_aStandardCandles[] =
431 {
432#ifdef IN_RING0
433# define KNOWN_ENTRY(a_Sym) { #a_Sym, (uintptr_t)&a_Sym }
434#else
435# define KNOWN_ENTRY(a_Sym) { #a_Sym, 0 }
436#endif
437 /* IOKit: */
438 KNOWN_ENTRY(IOMalloc),
439 KNOWN_ENTRY(IOFree),
440 KNOWN_ENTRY(IOSleep),
441 KNOWN_ENTRY(IORWLockAlloc),
442 KNOWN_ENTRY(IORecursiveLockLock),
443 KNOWN_ENTRY(IOSimpleLockAlloc),
444 KNOWN_ENTRY(PE_cpu_halt),
445 KNOWN_ENTRY(gIOKitDebug),
446 KNOWN_ENTRY(gIOServicePlane),
447 KNOWN_ENTRY(ev_try_lock),
448
449 /* Libkern: */
450 KNOWN_ENTRY(OSAddAtomic),
451 KNOWN_ENTRY(OSBitAndAtomic),
452 KNOWN_ENTRY(OSBitOrAtomic),
453 KNOWN_ENTRY(OSBitXorAtomic),
454 KNOWN_ENTRY(OSCompareAndSwap),
455 KNOWN_ENTRY(OSMalloc),
456 KNOWN_ENTRY(OSlibkernInit),
457 KNOWN_ENTRY(bcmp),
458 KNOWN_ENTRY(copyout),
459 KNOWN_ENTRY(copyin),
460 KNOWN_ENTRY(kprintf),
461 KNOWN_ENTRY(printf),
462 KNOWN_ENTRY(lck_grp_alloc_init),
463 KNOWN_ENTRY(lck_mtx_alloc_init),
464 KNOWN_ENTRY(lck_rw_alloc_init),
465 KNOWN_ENTRY(lck_spin_alloc_init),
466 KNOWN_ENTRY(osrelease),
467 KNOWN_ENTRY(ostype),
468 KNOWN_ENTRY(panic),
469 KNOWN_ENTRY(strprefix),
470 //KNOWN_ENTRY(sysctlbyname), - we get kernel_sysctlbyname from the 10.10+ kernels.
471 KNOWN_ENTRY(vsscanf),
472 KNOWN_ENTRY(page_mask),
473
474 /* Mach: */
475 KNOWN_ENTRY(absolutetime_to_nanoseconds),
476 KNOWN_ENTRY(assert_wait),
477 KNOWN_ENTRY(clock_delay_until),
478 KNOWN_ENTRY(clock_get_uptime),
479 KNOWN_ENTRY(current_task),
480 KNOWN_ENTRY(current_thread),
481 KNOWN_ENTRY(kernel_task),
482 KNOWN_ENTRY(lck_mtx_sleep),
483 KNOWN_ENTRY(lck_rw_sleep),
484 KNOWN_ENTRY(lck_spin_sleep),
485 KNOWN_ENTRY(mach_absolute_time),
486 KNOWN_ENTRY(semaphore_create),
487 KNOWN_ENTRY(task_reference),
488 KNOWN_ENTRY(thread_block),
489 KNOWN_ENTRY(thread_reference),
490 KNOWN_ENTRY(thread_terminate),
491 KNOWN_ENTRY(thread_wakeup_prim),
492
493 /* BSDKernel: */
494 KNOWN_ENTRY(buf_size),
495 KNOWN_ENTRY(copystr),
496 KNOWN_ENTRY(current_proc),
497 KNOWN_ENTRY(ifnet_hdrlen),
498 KNOWN_ENTRY(ifnet_set_promiscuous),
499 KNOWN_ENTRY(kauth_getuid),
500#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
501 KNOWN_ENTRY(kauth_cred_unref),
502#else
503 KNOWN_ENTRY(kauth_cred_rele),
504#endif
505 KNOWN_ENTRY(mbuf_data),
506 KNOWN_ENTRY(msleep),
507 KNOWN_ENTRY(nanotime),
508 KNOWN_ENTRY(nop_close),
509 KNOWN_ENTRY(proc_pid),
510 KNOWN_ENTRY(sock_accept),
511 KNOWN_ENTRY(sockopt_name),
512 //KNOWN_ENTRY(spec_write),
513 KNOWN_ENTRY(suword),
514 //KNOWN_ENTRY(sysctl_int),
515 KNOWN_ENTRY(uio_rw),
516 KNOWN_ENTRY(vfs_flags),
517 KNOWN_ENTRY(vfs_name),
518 KNOWN_ENTRY(vfs_statfs),
519 KNOWN_ENTRY(VNOP_READ),
520 KNOWN_ENTRY(uio_create),
521 KNOWN_ENTRY(uio_addiov),
522 KNOWN_ENTRY(uio_free),
523 KNOWN_ENTRY(vnode_get),
524 KNOWN_ENTRY(vnode_open),
525 KNOWN_ENTRY(vnode_ref),
526 KNOWN_ENTRY(vnode_rele),
527 KNOWN_ENTRY(vnop_close_desc),
528 KNOWN_ENTRY(wakeup),
529 KNOWN_ENTRY(wakeup_one),
530
531 /* Unsupported: */
532 KNOWN_ENTRY(kdp_set_interface),
533 KNOWN_ENTRY(pmap_find_phys),
534 KNOWN_ENTRY(vm_map),
535 KNOWN_ENTRY(vm_protect),
536 KNOWN_ENTRY(vm_region),
537 KNOWN_ENTRY(vm_map_unwire), /* vm_map_wire has an alternative symbol, vm_map_wire_external, in 10.11 */
538 KNOWN_ENTRY(PE_kputc),
539 KNOWN_ENTRY(kernel_map),
540 KNOWN_ENTRY(kernel_pmap),
541 };
542
543 for (unsigned i = 0; i < RT_ELEMENTS(s_aStandardCandles); i++)
544 {
545 uintptr_t uAddr = rtR0DbgKrnlDarwinLookup(pThis, s_aStandardCandles[i].pszName);
546#ifdef IN_RING0
547 if (uAddr != s_aStandardCandles[i].uAddr)
548#else
549 if (uAddr == 0)
550#endif
551 {
552 AssertLogRelMsgFailed(("%s (%p != %p)\n", s_aStandardCandles[i].pszName, uAddr, s_aStandardCandles[i].uAddr));
553 return VERR_INTERNAL_ERROR_2;
554 }
555 }
556 return VINF_SUCCESS;
557}
558
559
560/**
561 * Loads and validates the symbol and string tables.
562 *
563 * @returns IPRT status code.
564 * @param pThis The internal scratch data.
565 */
566static int rtR0DbgKrnlDarwinLoadSymTab(RTDBGKRNLINFOINT *pThis)
567{
568 /*
569 * Load the tables.
570 */
571 pThis->paSyms = (MY_NLIST *)RTMemAllocZ(pThis->cSyms * sizeof(MY_NLIST));
572 if (!pThis->paSyms)
573 return VERR_NO_MEMORY;
574
575 int rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offSyms,
576 pThis->paSyms, pThis->cSyms * sizeof(MY_NLIST), NULL);
577 if (RT_FAILURE(rc))
578 return rc;
579
580 pThis->pachStrTab = (char *)RTMemAllocZ(pThis->cbStrTab + 1);
581 if (!pThis->pachStrTab)
582 return VERR_NO_MEMORY;
583
584 rc = RTFileReadAt(pThis->hFile, pThis->offArch + pThis->offStrTab,
585 pThis->pachStrTab, pThis->cbStrTab, NULL);
586 if (RT_FAILURE(rc))
587 return rc;
588
589 /*
590 * The first string table symbol must be a zero length name.
591 */
592 if (pThis->pachStrTab[0] != '\0')
593 RETURN_VERR_BAD_EXE_FORMAT;
594
595 /*
596 * Validate the symbol table.
597 */
598 const char *pszPrev = "";
599 uint32_t const cSyms = pThis->cSyms;
600 MY_NLIST const *pSym = pThis->paSyms;
601 for (uint32_t iSym = 0; iSym < cSyms; iSym++, pSym++)
602 {
603 if ((uint32_t)pSym->n_un.n_strx >= pThis->cbStrTab)
604 RETURN_VERR_BAD_EXE_FORMAT;
605 const char *pszSym = &pThis->pachStrTab[(uint32_t)pSym->n_un.n_strx];
606#ifdef IN_RING3
607 RTAssertMsg2("%05i: %02x:%08llx %02x %04x %s\n", iSym, pSym->n_sect, (uint64_t)pSym->n_value, pSym->n_type, pSym->n_desc, pszSym);
608#endif
609
610 if (strcmp(pszSym, pszPrev) < 0)
611 RETURN_VERR_BAD_EXE_FORMAT; /* not sorted */
612
613 if (!(pSym->n_type & MACHO_N_STAB))
614 {
615 switch (pSym->n_type & MACHO_N_TYPE)
616 {
617 case MACHO_N_SECT:
618 if (pSym->n_sect == MACHO_NO_SECT)
619 RETURN_VERR_BAD_EXE_FORMAT;
620 if (pSym->n_sect > pThis->cSections)
621 RETURN_VERR_BAD_EXE_FORMAT;
622 if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY))
623 RETURN_VERR_BAD_EXE_FORMAT;
624 if ( pSym->n_value < pThis->apSections[pSym->n_sect - 1]->addr
625 && strcmp(pszSym, "__mh_execute_header")) /* in 10.8 it's no longer absolute (PIE?). */
626 RETURN_VERR_BAD_EXE_FORMAT;
627 if ( pSym->n_value - pThis->apSections[pSym->n_sect - 1]->addr
628 > pThis->apSections[pSym->n_sect - 1]->size
629 && strcmp(pszSym, "__mh_execute_header")) /* see above. */
630 RETURN_VERR_BAD_EXE_FORMAT;
631 break;
632
633 case MACHO_N_ABS:
634 if ( pSym->n_sect != MACHO_NO_SECT
635 && ( strcmp(pszSym, "__mh_execute_header") /* n_sect=1 in 10.7/amd64 */
636 || pSym->n_sect > pThis->cSections) )
637 RETURN_VERR_BAD_EXE_FORMAT;
638 if (pSym->n_desc & ~(REFERENCED_DYNAMICALLY))
639 RETURN_VERR_BAD_EXE_FORMAT;
640 break;
641
642 case MACHO_N_UNDF:
643 /* No undefined or common symbols in the kernel. */
644 RETURN_VERR_BAD_EXE_FORMAT;
645
646 case MACHO_N_INDR:
647 /* No indirect symbols in the kernel. */
648 RETURN_VERR_BAD_EXE_FORMAT;
649
650 case MACHO_N_PBUD:
651 /* No prebound symbols in the kernel. */
652 RETURN_VERR_BAD_EXE_FORMAT;
653
654 default:
655 RETURN_VERR_BAD_EXE_FORMAT;
656 }
657 }
658 /* else: Ignore debug symbols. */
659 }
660
661 return VINF_SUCCESS;
662}
663
664
665/**
666 * Loads the load commands and validates them.
667 *
668 * @returns IPRT status code.
669 * @param pThis The internal scratch data.
670 */
671static int rtR0DbgKrnlDarwinLoadCommands(RTDBGKRNLINFOINT *pThis)
672{
673 pThis->offStrTab = 0;
674 pThis->cbStrTab = 0;
675 pThis->offSyms = 0;
676 pThis->cSyms = 0;
677 pThis->cSections = 0;
678
679 pThis->pLoadCmds = (load_command_t *)RTMemAlloc(pThis->cbLoadCmds);
680 if (!pThis->pLoadCmds)
681 return VERR_NO_MEMORY;
682
683 int rc = RTFileReadAt(pThis->hFile, pThis->offArch + sizeof(MY_MACHO_HEADER),
684 pThis->pLoadCmds, pThis->cbLoadCmds, NULL);
685 if (RT_FAILURE(rc))
686 return rc;
687
688 /*
689 * Validate the relevant commands, picking up sections and the symbol
690 * table location.
691 */
692 load_command_t const *pCmd = pThis->pLoadCmds;
693 for (uint32_t iCmd = 0; ; iCmd++)
694 {
695 /* cmd index & offset. */
696 uintptr_t offCmd = (uintptr_t)pCmd - (uintptr_t)pThis->pLoadCmds;
697 if (offCmd == pThis->cbLoadCmds && iCmd == pThis->cLoadCmds)
698 break;
699 if (offCmd + sizeof(*pCmd) > pThis->cbLoadCmds)
700 RETURN_VERR_BAD_EXE_FORMAT;
701 if (iCmd >= pThis->cLoadCmds)
702 RETURN_VERR_BAD_EXE_FORMAT;
703
704 /* cmdsize */
705 if (pCmd->cmdsize < sizeof(*pCmd))
706 RETURN_VERR_BAD_EXE_FORMAT;
707 if (pCmd->cmdsize > pThis->cbLoadCmds)
708 RETURN_VERR_BAD_EXE_FORMAT;
709 if (RT_ALIGN_32(pCmd->cmdsize, 4) != pCmd->cmdsize)
710 RETURN_VERR_BAD_EXE_FORMAT;
711
712 /* cmd */
713 switch (pCmd->cmd & ~LC_REQ_DYLD)
714 {
715 /* Validate and store the symbol table details. */
716 case LC_SYMTAB:
717 {
718 struct symtab_command const *pSymTab = (struct symtab_command const *)pCmd;
719 if (pSymTab->cmdsize != sizeof(*pSymTab))
720 RETURN_VERR_BAD_EXE_FORMAT;
721 if (pSymTab->nsyms > _1M)
722 RETURN_VERR_BAD_EXE_FORMAT;
723 if (pSymTab->strsize > _2M)
724 RETURN_VERR_BAD_EXE_FORMAT;
725
726 pThis->offStrTab = pSymTab->stroff;
727 pThis->cbStrTab = pSymTab->strsize;
728 pThis->offSyms = pSymTab->symoff;
729 pThis->cSyms = pSymTab->nsyms;
730 break;
731 }
732
733 /* Validate the segment. */
734#if ARCH_BITS == 32
735 case LC_SEGMENT_32:
736#elif ARCH_BITS == 64
737 case LC_SEGMENT_64:
738#else
739# error ARCH_BITS
740#endif
741 {
742 MY_SEGMENT_COMMAND const *pSeg = (MY_SEGMENT_COMMAND const *)pCmd;
743 if (pSeg->cmdsize < sizeof(*pSeg))
744 RETURN_VERR_BAD_EXE_FORMAT;
745
746 if (pSeg->segname[0] == '\0')
747 RETURN_VERR_BAD_EXE_FORMAT;
748
749 if (pSeg->nsects > MACHO_MAX_SECT)
750 RETURN_VERR_BAD_EXE_FORMAT;
751 if (pSeg->nsects * sizeof(MY_SECTION) + sizeof(*pSeg) != pSeg->cmdsize)
752 RETURN_VERR_BAD_EXE_FORMAT;
753
754 if (pSeg->flags & ~(SG_HIGHVM | SG_FVMLIB | SG_NORELOC | SG_PROTECTED_VERSION_1))
755 RETURN_VERR_BAD_EXE_FORMAT;
756
757 if ( pSeg->vmaddr != 0
758 || !strcmp(pSeg->segname, "__PAGEZERO"))
759 {
760 if (pSeg->vmaddr + RT_ALIGN_Z(pSeg->vmsize, RT_BIT_32(12)) < pSeg->vmaddr)
761 RETURN_VERR_BAD_EXE_FORMAT;
762 }
763 else if (pSeg->vmsize)
764 RETURN_VERR_BAD_EXE_FORMAT;
765
766 if (pSeg->maxprot & ~VM_PROT_ALL)
767 RETURN_VERR_BAD_EXE_FORMAT;
768 if (pSeg->initprot & ~VM_PROT_ALL)
769 RETURN_VERR_BAD_EXE_FORMAT;
770
771 /* Validate the sections. */
772 uint32_t uAlignment = 0;
773 uintptr_t uAddr = pSeg->vmaddr;
774 MY_SECTION const *paSects = (MY_SECTION const *)(pSeg + 1);
775 for (uint32_t i = 0; i < pSeg->nsects; i++)
776 {
777 if (paSects[i].sectname[0] == '\0')
778 RETURN_VERR_BAD_EXE_FORMAT;
779 if (memcmp(paSects[i].segname, pSeg->segname, sizeof(pSeg->segname)))
780 RETURN_VERR_BAD_EXE_FORMAT;
781
782 switch (paSects[i].flags & SECTION_TYPE)
783 {
784 case S_REGULAR:
785 case S_CSTRING_LITERALS:
786 case S_NON_LAZY_SYMBOL_POINTERS:
787 case S_MOD_INIT_FUNC_POINTERS:
788 case S_MOD_TERM_FUNC_POINTERS:
789 case S_COALESCED:
790 case S_4BYTE_LITERALS:
791 if ( pSeg->filesize != 0
792 ? paSects[i].offset - pSeg->fileoff >= pSeg->filesize
793 : paSects[i].offset - pSeg->fileoff != pSeg->filesize)
794 RETURN_VERR_BAD_EXE_FORMAT;
795 if ( paSects[i].addr != 0
796 && paSects[i].offset - pSeg->fileoff != paSects[i].addr - pSeg->vmaddr)
797 RETURN_VERR_BAD_EXE_FORMAT;
798 break;
799
800 case S_ZEROFILL:
801 if (paSects[i].offset != 0)
802 RETURN_VERR_BAD_EXE_FORMAT;
803 break;
804
805 /* not observed */
806 case S_SYMBOL_STUBS:
807 case S_INTERPOSING:
808 case S_8BYTE_LITERALS:
809 case S_16BYTE_LITERALS:
810 case S_DTRACE_DOF:
811 case S_LAZY_SYMBOL_POINTERS:
812 case S_LAZY_DYLIB_SYMBOL_POINTERS:
813 RETURN_VERR_LDR_UNEXPECTED;
814 case S_GB_ZEROFILL:
815 RETURN_VERR_LDR_UNEXPECTED;
816 default:
817 RETURN_VERR_BAD_EXE_FORMAT;
818 }
819
820 if (paSects[i].align > 12)
821 RETURN_VERR_BAD_EXE_FORMAT;
822 if (paSects[i].align > uAlignment)
823 uAlignment = paSects[i].align;
824
825 /* Add to the section table. */
826 if (pThis->cSections == MACHO_MAX_SECT)
827 RETURN_VERR_BAD_EXE_FORMAT;
828 pThis->apSections[pThis->cSections++] = &paSects[i];
829 }
830
831 if (RT_ALIGN_Z(pSeg->vmaddr, RT_BIT_32(uAlignment)) != pSeg->vmaddr)
832 RETURN_VERR_BAD_EXE_FORMAT;
833 if ( pSeg->filesize > RT_ALIGN_Z(pSeg->vmsize, RT_BIT_32(uAlignment))
834 && pSeg->vmsize != 0)
835 RETURN_VERR_BAD_EXE_FORMAT;
836 break;
837 }
838
839 case LC_UUID:
840 if (pCmd->cmdsize != sizeof(uuid_command))
841 RETURN_VERR_BAD_EXE_FORMAT;
842 break;
843
844 case LC_DYSYMTAB:
845 case LC_UNIXTHREAD:
846 case LC_CODE_SIGNATURE:
847 case LC_VERSION_MIN_MACOSX:
848 case LC_FUNCTION_STARTS:
849 case LC_MAIN:
850 case LC_DATA_IN_CODE:
851 case LC_SOURCE_VERSION:
852 break;
853
854 /* not observed */
855 case LC_SYMSEG:
856#if ARCH_BITS == 32
857 case LC_SEGMENT_64:
858#elif ARCH_BITS == 64
859 case LC_SEGMENT_32:
860#endif
861 case LC_ROUTINES_64:
862 case LC_ROUTINES:
863 case LC_THREAD:
864 case LC_LOADFVMLIB:
865 case LC_IDFVMLIB:
866 case LC_IDENT:
867 case LC_FVMFILE:
868 case LC_PREPAGE:
869 case LC_TWOLEVEL_HINTS:
870 case LC_PREBIND_CKSUM:
871 case LC_SEGMENT_SPLIT_INFO:
872 case LC_ENCRYPTION_INFO:
873 RETURN_VERR_LDR_UNEXPECTED;
874
875 /* no phones here yet */
876 case LC_VERSION_MIN_IPHONEOS:
877 RETURN_VERR_LDR_UNEXPECTED;
878
879 /* dylib */
880 case LC_LOAD_DYLIB:
881 case LC_ID_DYLIB:
882 case LC_LOAD_DYLINKER:
883 case LC_ID_DYLINKER:
884 case LC_PREBOUND_DYLIB:
885 case LC_LOAD_WEAK_DYLIB & ~LC_REQ_DYLD:
886 case LC_SUB_FRAMEWORK:
887 case LC_SUB_UMBRELLA:
888 case LC_SUB_CLIENT:
889 case LC_SUB_LIBRARY:
890 case LC_RPATH:
891 case LC_REEXPORT_DYLIB:
892 case LC_LAZY_LOAD_DYLIB:
893 case LC_DYLD_INFO:
894 case LC_DYLD_INFO_ONLY:
895 case LC_LOAD_UPWARD_DYLIB:
896 case LC_DYLD_ENVIRONMENT:
897 case LC_DYLIB_CODE_SIGN_DRS:
898 RETURN_VERR_LDR_UNEXPECTED;
899
900 default:
901 RETURN_VERR_BAD_EXE_FORMAT;
902 }
903
904 /* next */
905 pCmd = (load_command_t *)((uintptr_t)pCmd + pCmd->cmdsize);
906 }
907
908 return VINF_SUCCESS;
909}
910
911
912/**
913 * Loads the FAT and MACHO headers, noting down the relevant info.
914 *
915 * @returns IPRT status code.
916 * @param pThis The internal scratch data.
917 */
918static int rtR0DbgKrnlDarwinLoadFileHeaders(RTDBGKRNLINFOINT *pThis)
919{
920 uint32_t i;
921
922 pThis->offArch = 0;
923 pThis->cbArch = 0;
924
925 /*
926 * Read the first bit of the file, parse the FAT if found there.
927 */
928 int rc = RTFileReadAt(pThis->hFile, 0, pThis->abBuf, sizeof(fat_header_t) + sizeof(fat_arch_t) * 16, NULL);
929 if (RT_FAILURE(rc))
930 return rc;
931
932 fat_header_t *pFat = (fat_header *)pThis->abBuf;
933 fat_arch_t *paFatArches = (fat_arch_t *)(pFat + 1);
934
935 /* Correct FAT endian first. */
936 if (pFat->magic == IMAGE_FAT_SIGNATURE_OE)
937 {
938 pFat->magic = RT_BSWAP_U32(pFat->magic);
939 pFat->nfat_arch = RT_BSWAP_U32(pFat->nfat_arch);
940 i = RT_MIN(pFat->nfat_arch, 16);
941 while (i-- > 0)
942 {
943 paFatArches[i].cputype = RT_BSWAP_U32(paFatArches[i].cputype);
944 paFatArches[i].cpusubtype = RT_BSWAP_U32(paFatArches[i].cpusubtype);
945 paFatArches[i].offset = RT_BSWAP_U32(paFatArches[i].offset);
946 paFatArches[i].size = RT_BSWAP_U32(paFatArches[i].size);
947 paFatArches[i].align = RT_BSWAP_U32(paFatArches[i].align);
948 }
949 }
950
951 /* Lookup our architecture in the FAT. */
952 if (pFat->magic == IMAGE_FAT_SIGNATURE)
953 {
954 if (pFat->nfat_arch > 16)
955 RETURN_VERR_BAD_EXE_FORMAT;
956
957 for (i = 0; i < pFat->nfat_arch; i++)
958 {
959 if ( paFatArches[i].cputype == MY_CPU_TYPE
960 && paFatArches[i].cpusubtype == MY_CPU_SUBTYPE_ALL)
961 {
962 pThis->offArch = paFatArches[i].offset;
963 pThis->cbArch = paFatArches[i].size;
964 if (!pThis->cbArch)
965 RETURN_VERR_BAD_EXE_FORMAT;
966 if (pThis->offArch < sizeof(fat_header_t) + sizeof(fat_arch_t) * pFat->nfat_arch)
967 RETURN_VERR_BAD_EXE_FORMAT;
968 if (pThis->offArch + pThis->cbArch <= pThis->offArch)
969 RETURN_VERR_LDR_ARCH_MISMATCH;
970 break;
971 }
972 }
973 if (i >= pFat->nfat_arch)
974 RETURN_VERR_LDR_ARCH_MISMATCH;
975 }
976
977 /*
978 * Read the Mach-O header and validate it.
979 */
980 rc = RTFileReadAt(pThis->hFile, pThis->offArch, pThis->abBuf, sizeof(MY_MACHO_HEADER), NULL);
981 if (RT_FAILURE(rc))
982 return rc;
983 MY_MACHO_HEADER const *pHdr = (MY_MACHO_HEADER const *)pThis->abBuf;
984 if (pHdr->magic != MY_MACHO_MAGIC)
985 {
986 if ( pHdr->magic == IMAGE_MACHO32_SIGNATURE
987 || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
988 || pHdr->magic == IMAGE_MACHO64_SIGNATURE
989 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE)
990 RETURN_VERR_LDR_ARCH_MISMATCH;
991 RETURN_VERR_BAD_EXE_FORMAT;
992 }
993
994 if (pHdr->cputype != MY_CPU_TYPE)
995 RETURN_VERR_LDR_ARCH_MISMATCH;
996 if (pHdr->cpusubtype != MY_CPU_SUBTYPE_ALL)
997 RETURN_VERR_LDR_ARCH_MISMATCH;
998 if (pHdr->filetype != MH_EXECUTE)
999 RETURN_VERR_LDR_UNEXPECTED;
1000 if (pHdr->ncmds < 4)
1001 RETURN_VERR_LDR_UNEXPECTED;
1002 if (pHdr->ncmds > 256)
1003 RETURN_VERR_LDR_UNEXPECTED;
1004 if (pHdr->sizeofcmds <= pHdr->ncmds * sizeof(load_command_t))
1005 RETURN_VERR_LDR_UNEXPECTED;
1006 if (pHdr->sizeofcmds >= _1M)
1007 RETURN_VERR_LDR_UNEXPECTED;
1008 if (pHdr->flags & ~MH_VALID_FLAGS)
1009 RETURN_VERR_LDR_UNEXPECTED;
1010
1011 pThis->cLoadCmds = pHdr->ncmds;
1012 pThis->cbLoadCmds = pHdr->sizeofcmds;
1013 return VINF_SUCCESS;
1014}
1015
1016
1017/**
1018 * Destructor.
1019 *
1020 * @param pThis The instance to destroy.
1021 */
1022static void rtR0DbgKrnlDarwinDtor(RTDBGKRNLINFOINT *pThis)
1023{
1024 pThis->u32Magic = ~RTDBGKRNLINFO_MAGIC;
1025
1026 RTMemFree(pThis->pachStrTab);
1027 pThis->pachStrTab = NULL;
1028
1029 RTMemFree(pThis->paSyms);
1030 pThis->paSyms = NULL;
1031
1032 RTMemFree(pThis);
1033}
1034
1035
1036static int rtR0DbgKrnlDarwinOpen(PRTDBGKRNLINFO phKrnlInfo, const char *pszKernelFile)
1037{
1038 RTDBGKRNLINFOINT *pThis = (RTDBGKRNLINFOINT *)RTMemAllocZ(sizeof(*pThis));
1039 if (!pThis)
1040 return VERR_NO_MEMORY;
1041 pThis->hFile = NIL_RTFILE;
1042
1043 int rc = RTFileOpen(&pThis->hFile, pszKernelFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
1044 if (RT_SUCCESS(rc))
1045 rc = rtR0DbgKrnlDarwinLoadFileHeaders(pThis);
1046 if (RT_SUCCESS(rc))
1047 rc = rtR0DbgKrnlDarwinLoadCommands(pThis);
1048 if (RT_SUCCESS(rc))
1049 rc = rtR0DbgKrnlDarwinLoadSymTab(pThis);
1050 if (RT_SUCCESS(rc))
1051 {
1052#ifdef IN_RING0
1053 /*
1054 * Determine the load displacement (10.8 kernels are PIE).
1055 */
1056 uintptr_t uLinkAddr = rtR0DbgKrnlDarwinLookup(pThis, "kernel_map");
1057 if (uLinkAddr != 0)
1058 pThis->offLoad = (uintptr_t)&kernel_map - uLinkAddr;
1059#endif
1060 rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis);
1061 }
1062
1063 rtR0DbgKrnlDarwinLoadDone(pThis);
1064 if (RT_SUCCESS(rc))
1065 {
1066 pThis->u32Magic = RTDBGKRNLINFO_MAGIC;
1067 pThis->cRefs = 1;
1068 *phKrnlInfo = pThis;
1069 }
1070 else
1071 rtR0DbgKrnlDarwinDtor(pThis);
1072 return rc;
1073}
1074
1075
1076RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags)
1077{
1078 AssertPtrReturn(phKrnlInfo, VERR_INVALID_POINTER);
1079 *phKrnlInfo = NIL_RTDBGKRNLINFO;
1080 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1081
1082 /*
1083 * Go thru likely kernel locations
1084 *
1085 * Note! Check the OS X version and reorder the list?
1086 * Note! We should try fish kcsuffix out of bootargs or somewhere one day.
1087 */
1088 static bool s_fFirstCall = true;
1089 struct
1090 {
1091 const char *pszLocation;
1092 int rc;
1093 } aKernels[] =
1094 {
1095 { "/System/Library/Kernels/kernel", VERR_WRONG_ORDER },
1096 { "/System/Library/Kernels/kernel.development", VERR_WRONG_ORDER },
1097 { "/System/Library/Kernels/kernel.debug", VERR_WRONG_ORDER },
1098 { "/mach_kernel", VERR_WRONG_ORDER },
1099 };
1100 int rc;
1101 for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
1102 {
1103 aKernels[i].rc = rc = rtR0DbgKrnlDarwinOpen(phKrnlInfo, aKernels[i].pszLocation);
1104 if (RT_SUCCESS(rc))
1105 {
1106 if (s_fFirstCall)
1107 {
1108 printf("RTR0DbgKrnlInfoOpen: Using kernel file '%s'\n", aKernels[i].pszLocation);
1109 s_fFirstCall = false;
1110 }
1111 return rc;
1112 }
1113 }
1114
1115 /*
1116 * Failed.
1117 */
1118 /* Pick the best error code. */
1119 for (uint32_t i = 0; rc == VERR_FILE_NOT_FOUND && i < RT_ELEMENTS(aKernels); i++)
1120 if (aKernels[i].rc != VERR_FILE_NOT_FOUND)
1121 rc = aKernels[i].rc;
1122
1123 /* Bitch about it. */
1124 printf("RTR0DbgKrnlInfoOpen: failed to find matching kernel file! rc=%d\n", rc);
1125 if (s_fFirstCall)
1126 {
1127 for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
1128 printf("RTR0DbgKrnlInfoOpen: '%s' -> %d\n", aKernels[i].pszLocation, aKernels[i].rc);
1129 s_fFirstCall = false;
1130 }
1131
1132 return rc;
1133}
1134
1135
1136RTR0DECL(uint32_t) RTR0DbgKrnlInfoRetain(RTDBGKRNLINFO hKrnlInfo)
1137{
1138 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1139 AssertPtrReturn(pThis, UINT32_MAX);
1140 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
1141
1142 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
1143 Assert(cRefs && cRefs < 100000);
1144 return cRefs;
1145}
1146
1147
1148RTR0DECL(uint32_t) RTR0DbgKrnlInfoRelease(RTDBGKRNLINFO hKrnlInfo)
1149{
1150 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1151 if (pThis == NIL_RTDBGKRNLINFO)
1152 return 0;
1153 AssertPtrReturn(pThis, UINT32_MAX);
1154 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
1155
1156 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1157 if (cRefs == 0)
1158 rtR0DbgKrnlDarwinDtor(pThis);
1159 return cRefs;
1160}
1161
1162
1163RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszStructure,
1164 const char *pszMember, size_t *poffMember)
1165{
1166 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1167 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1168 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
1169 AssertPtrReturn(pszMember, VERR_INVALID_PARAMETER);
1170 AssertPtrReturn(pszStructure, VERR_INVALID_PARAMETER);
1171 AssertPtrReturn(poffMember, VERR_INVALID_PARAMETER);
1172 return VERR_NOT_FOUND;
1173}
1174
1175
1176RTR0DECL(int) RTR0DbgKrnlInfoQuerySymbol(RTDBGKRNLINFO hKrnlInfo, const char *pszModule,
1177 const char *pszSymbol, void **ppvSymbol)
1178{
1179 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1180 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1181 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
1182 AssertPtrReturn(pszSymbol, VERR_INVALID_PARAMETER);
1183 AssertPtrNullReturn(ppvSymbol, VERR_INVALID_PARAMETER);
1184 AssertReturn(!pszModule, VERR_MODULE_NOT_FOUND);
1185
1186 uintptr_t uValue = rtR0DbgKrnlDarwinLookup(pThis, pszSymbol);
1187 if (ppvSymbol)
1188 *ppvSymbol = (void *)uValue;
1189 if (uValue)
1190 return VINF_SUCCESS;
1191 return VERR_SYMBOL_NOT_FOUND;
1192}
1193
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette