VirtualBox

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

Last change on this file since 64831 was 63451, checked in by vboxsync, 9 years ago

Runtime: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.9 KB
Line 
1/* $Id: dbgkrnlinfo-r0drv-darwin.cpp 63451 2016-08-15 00:39:40Z 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 MY_SECTION const *paSects = (MY_SECTION const *)(pSeg + 1);
774 for (uint32_t i = 0; i < pSeg->nsects; i++)
775 {
776 if (paSects[i].sectname[0] == '\0')
777 RETURN_VERR_BAD_EXE_FORMAT;
778 if (memcmp(paSects[i].segname, pSeg->segname, sizeof(pSeg->segname)))
779 RETURN_VERR_BAD_EXE_FORMAT;
780
781 switch (paSects[i].flags & SECTION_TYPE)
782 {
783 case S_REGULAR:
784 case S_CSTRING_LITERALS:
785 case S_NON_LAZY_SYMBOL_POINTERS:
786 case S_MOD_INIT_FUNC_POINTERS:
787 case S_MOD_TERM_FUNC_POINTERS:
788 case S_COALESCED:
789 case S_4BYTE_LITERALS:
790 if ( pSeg->filesize != 0
791 ? paSects[i].offset - pSeg->fileoff >= pSeg->filesize
792 : paSects[i].offset - pSeg->fileoff != pSeg->filesize)
793 RETURN_VERR_BAD_EXE_FORMAT;
794 if ( paSects[i].addr != 0
795 && paSects[i].offset - pSeg->fileoff != paSects[i].addr - pSeg->vmaddr)
796 RETURN_VERR_BAD_EXE_FORMAT;
797 break;
798
799 case S_ZEROFILL:
800 if (paSects[i].offset != 0)
801 RETURN_VERR_BAD_EXE_FORMAT;
802 break;
803
804 /* not observed */
805 case S_SYMBOL_STUBS:
806 case S_INTERPOSING:
807 case S_8BYTE_LITERALS:
808 case S_16BYTE_LITERALS:
809 case S_DTRACE_DOF:
810 case S_LAZY_SYMBOL_POINTERS:
811 case S_LAZY_DYLIB_SYMBOL_POINTERS:
812 RETURN_VERR_LDR_UNEXPECTED;
813 case S_GB_ZEROFILL:
814 RETURN_VERR_LDR_UNEXPECTED;
815 default:
816 RETURN_VERR_BAD_EXE_FORMAT;
817 }
818
819 if (paSects[i].align > 12)
820 RETURN_VERR_BAD_EXE_FORMAT;
821 if (paSects[i].align > uAlignment)
822 uAlignment = paSects[i].align;
823
824 /* Add to the section table. */
825 if (pThis->cSections == MACHO_MAX_SECT)
826 RETURN_VERR_BAD_EXE_FORMAT;
827 pThis->apSections[pThis->cSections++] = &paSects[i];
828 }
829
830 if (RT_ALIGN_Z(pSeg->vmaddr, RT_BIT_32(uAlignment)) != pSeg->vmaddr)
831 RETURN_VERR_BAD_EXE_FORMAT;
832 if ( pSeg->filesize > RT_ALIGN_Z(pSeg->vmsize, RT_BIT_32(uAlignment))
833 && pSeg->vmsize != 0)
834 RETURN_VERR_BAD_EXE_FORMAT;
835 break;
836 }
837
838 case LC_UUID:
839 if (pCmd->cmdsize != sizeof(uuid_command))
840 RETURN_VERR_BAD_EXE_FORMAT;
841 break;
842
843 case LC_DYSYMTAB:
844 case LC_UNIXTHREAD:
845 case LC_CODE_SIGNATURE:
846 case LC_VERSION_MIN_MACOSX:
847 case LC_FUNCTION_STARTS:
848 case LC_MAIN:
849 case LC_DATA_IN_CODE:
850 case LC_SOURCE_VERSION:
851 break;
852
853 /* not observed */
854 case LC_SYMSEG:
855#if ARCH_BITS == 32
856 case LC_SEGMENT_64:
857#elif ARCH_BITS == 64
858 case LC_SEGMENT_32:
859#endif
860 case LC_ROUTINES_64:
861 case LC_ROUTINES:
862 case LC_THREAD:
863 case LC_LOADFVMLIB:
864 case LC_IDFVMLIB:
865 case LC_IDENT:
866 case LC_FVMFILE:
867 case LC_PREPAGE:
868 case LC_TWOLEVEL_HINTS:
869 case LC_PREBIND_CKSUM:
870 case LC_SEGMENT_SPLIT_INFO:
871 case LC_ENCRYPTION_INFO:
872 RETURN_VERR_LDR_UNEXPECTED;
873
874 /* no phones here yet */
875 case LC_VERSION_MIN_IPHONEOS:
876 RETURN_VERR_LDR_UNEXPECTED;
877
878 /* dylib */
879 case LC_LOAD_DYLIB:
880 case LC_ID_DYLIB:
881 case LC_LOAD_DYLINKER:
882 case LC_ID_DYLINKER:
883 case LC_PREBOUND_DYLIB:
884 case LC_LOAD_WEAK_DYLIB & ~LC_REQ_DYLD:
885 case LC_SUB_FRAMEWORK:
886 case LC_SUB_UMBRELLA:
887 case LC_SUB_CLIENT:
888 case LC_SUB_LIBRARY:
889 case LC_RPATH:
890 case LC_REEXPORT_DYLIB:
891 case LC_LAZY_LOAD_DYLIB:
892 case LC_DYLD_INFO:
893 case LC_DYLD_INFO_ONLY:
894 case LC_LOAD_UPWARD_DYLIB:
895 case LC_DYLD_ENVIRONMENT:
896 case LC_DYLIB_CODE_SIGN_DRS:
897 RETURN_VERR_LDR_UNEXPECTED;
898
899 default:
900 RETURN_VERR_BAD_EXE_FORMAT;
901 }
902
903 /* next */
904 pCmd = (load_command_t *)((uintptr_t)pCmd + pCmd->cmdsize);
905 }
906
907 return VINF_SUCCESS;
908}
909
910
911/**
912 * Loads the FAT and MACHO headers, noting down the relevant info.
913 *
914 * @returns IPRT status code.
915 * @param pThis The internal scratch data.
916 */
917static int rtR0DbgKrnlDarwinLoadFileHeaders(RTDBGKRNLINFOINT *pThis)
918{
919 uint32_t i;
920
921 pThis->offArch = 0;
922 pThis->cbArch = 0;
923
924 /*
925 * Read the first bit of the file, parse the FAT if found there.
926 */
927 int rc = RTFileReadAt(pThis->hFile, 0, pThis->abBuf, sizeof(fat_header_t) + sizeof(fat_arch_t) * 16, NULL);
928 if (RT_FAILURE(rc))
929 return rc;
930
931 fat_header_t *pFat = (fat_header *)pThis->abBuf;
932 fat_arch_t *paFatArches = (fat_arch_t *)(pFat + 1);
933
934 /* Correct FAT endian first. */
935 if (pFat->magic == IMAGE_FAT_SIGNATURE_OE)
936 {
937 pFat->magic = RT_BSWAP_U32(pFat->magic);
938 pFat->nfat_arch = RT_BSWAP_U32(pFat->nfat_arch);
939 i = RT_MIN(pFat->nfat_arch, 16);
940 while (i-- > 0)
941 {
942 paFatArches[i].cputype = RT_BSWAP_U32(paFatArches[i].cputype);
943 paFatArches[i].cpusubtype = RT_BSWAP_U32(paFatArches[i].cpusubtype);
944 paFatArches[i].offset = RT_BSWAP_U32(paFatArches[i].offset);
945 paFatArches[i].size = RT_BSWAP_U32(paFatArches[i].size);
946 paFatArches[i].align = RT_BSWAP_U32(paFatArches[i].align);
947 }
948 }
949
950 /* Lookup our architecture in the FAT. */
951 if (pFat->magic == IMAGE_FAT_SIGNATURE)
952 {
953 if (pFat->nfat_arch > 16)
954 RETURN_VERR_BAD_EXE_FORMAT;
955
956 for (i = 0; i < pFat->nfat_arch; i++)
957 {
958 if ( paFatArches[i].cputype == MY_CPU_TYPE
959 && paFatArches[i].cpusubtype == MY_CPU_SUBTYPE_ALL)
960 {
961 pThis->offArch = paFatArches[i].offset;
962 pThis->cbArch = paFatArches[i].size;
963 if (!pThis->cbArch)
964 RETURN_VERR_BAD_EXE_FORMAT;
965 if (pThis->offArch < sizeof(fat_header_t) + sizeof(fat_arch_t) * pFat->nfat_arch)
966 RETURN_VERR_BAD_EXE_FORMAT;
967 if (pThis->offArch + pThis->cbArch <= pThis->offArch)
968 RETURN_VERR_LDR_ARCH_MISMATCH;
969 break;
970 }
971 }
972 if (i >= pFat->nfat_arch)
973 RETURN_VERR_LDR_ARCH_MISMATCH;
974 }
975
976 /*
977 * Read the Mach-O header and validate it.
978 */
979 rc = RTFileReadAt(pThis->hFile, pThis->offArch, pThis->abBuf, sizeof(MY_MACHO_HEADER), NULL);
980 if (RT_FAILURE(rc))
981 return rc;
982 MY_MACHO_HEADER const *pHdr = (MY_MACHO_HEADER const *)pThis->abBuf;
983 if (pHdr->magic != MY_MACHO_MAGIC)
984 {
985 if ( pHdr->magic == IMAGE_MACHO32_SIGNATURE
986 || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
987 || pHdr->magic == IMAGE_MACHO64_SIGNATURE
988 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE)
989 RETURN_VERR_LDR_ARCH_MISMATCH;
990 RETURN_VERR_BAD_EXE_FORMAT;
991 }
992
993 if (pHdr->cputype != MY_CPU_TYPE)
994 RETURN_VERR_LDR_ARCH_MISMATCH;
995 if (pHdr->cpusubtype != MY_CPU_SUBTYPE_ALL)
996 RETURN_VERR_LDR_ARCH_MISMATCH;
997 if (pHdr->filetype != MH_EXECUTE)
998 RETURN_VERR_LDR_UNEXPECTED;
999 if (pHdr->ncmds < 4)
1000 RETURN_VERR_LDR_UNEXPECTED;
1001 if (pHdr->ncmds > 256)
1002 RETURN_VERR_LDR_UNEXPECTED;
1003 if (pHdr->sizeofcmds <= pHdr->ncmds * sizeof(load_command_t))
1004 RETURN_VERR_LDR_UNEXPECTED;
1005 if (pHdr->sizeofcmds >= _1M)
1006 RETURN_VERR_LDR_UNEXPECTED;
1007 if (pHdr->flags & ~MH_VALID_FLAGS)
1008 RETURN_VERR_LDR_UNEXPECTED;
1009
1010 pThis->cLoadCmds = pHdr->ncmds;
1011 pThis->cbLoadCmds = pHdr->sizeofcmds;
1012 return VINF_SUCCESS;
1013}
1014
1015
1016/**
1017 * Destructor.
1018 *
1019 * @param pThis The instance to destroy.
1020 */
1021static void rtR0DbgKrnlDarwinDtor(RTDBGKRNLINFOINT *pThis)
1022{
1023 pThis->u32Magic = ~RTDBGKRNLINFO_MAGIC;
1024
1025 RTMemFree(pThis->pachStrTab);
1026 pThis->pachStrTab = NULL;
1027
1028 RTMemFree(pThis->paSyms);
1029 pThis->paSyms = NULL;
1030
1031 RTMemFree(pThis);
1032}
1033
1034
1035static int rtR0DbgKrnlDarwinOpen(PRTDBGKRNLINFO phKrnlInfo, const char *pszKernelFile)
1036{
1037 RTDBGKRNLINFOINT *pThis = (RTDBGKRNLINFOINT *)RTMemAllocZ(sizeof(*pThis));
1038 if (!pThis)
1039 return VERR_NO_MEMORY;
1040 pThis->hFile = NIL_RTFILE;
1041
1042 int rc = RTFileOpen(&pThis->hFile, pszKernelFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
1043 if (RT_SUCCESS(rc))
1044 rc = rtR0DbgKrnlDarwinLoadFileHeaders(pThis);
1045 if (RT_SUCCESS(rc))
1046 rc = rtR0DbgKrnlDarwinLoadCommands(pThis);
1047 if (RT_SUCCESS(rc))
1048 rc = rtR0DbgKrnlDarwinLoadSymTab(pThis);
1049 if (RT_SUCCESS(rc))
1050 {
1051#ifdef IN_RING0
1052 /*
1053 * Determine the load displacement (10.8 kernels are PIE).
1054 */
1055 uintptr_t uLinkAddr = rtR0DbgKrnlDarwinLookup(pThis, "kernel_map");
1056 if (uLinkAddr != 0)
1057 pThis->offLoad = (uintptr_t)&kernel_map - uLinkAddr;
1058#endif
1059 rc = rtR0DbgKrnlDarwinCheckStandardSymbols(pThis);
1060 }
1061
1062 rtR0DbgKrnlDarwinLoadDone(pThis);
1063 if (RT_SUCCESS(rc))
1064 {
1065 pThis->u32Magic = RTDBGKRNLINFO_MAGIC;
1066 pThis->cRefs = 1;
1067 *phKrnlInfo = pThis;
1068 }
1069 else
1070 rtR0DbgKrnlDarwinDtor(pThis);
1071 return rc;
1072}
1073
1074
1075RTR0DECL(int) RTR0DbgKrnlInfoOpen(PRTDBGKRNLINFO phKrnlInfo, uint32_t fFlags)
1076{
1077 AssertPtrReturn(phKrnlInfo, VERR_INVALID_POINTER);
1078 *phKrnlInfo = NIL_RTDBGKRNLINFO;
1079 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
1080
1081 /*
1082 * Go thru likely kernel locations
1083 *
1084 * Note! Check the OS X version and reorder the list?
1085 * Note! We should try fish kcsuffix out of bootargs or somewhere one day.
1086 */
1087 static bool s_fFirstCall = true;
1088 struct
1089 {
1090 const char *pszLocation;
1091 int rc;
1092 } aKernels[] =
1093 {
1094 { "/System/Library/Kernels/kernel", VERR_WRONG_ORDER },
1095 { "/System/Library/Kernels/kernel.development", VERR_WRONG_ORDER },
1096 { "/System/Library/Kernels/kernel.debug", VERR_WRONG_ORDER },
1097 { "/mach_kernel", VERR_WRONG_ORDER },
1098 };
1099 int rc;
1100 for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
1101 {
1102 aKernels[i].rc = rc = rtR0DbgKrnlDarwinOpen(phKrnlInfo, aKernels[i].pszLocation);
1103 if (RT_SUCCESS(rc))
1104 {
1105 if (s_fFirstCall)
1106 {
1107 printf("RTR0DbgKrnlInfoOpen: Using kernel file '%s'\n", aKernels[i].pszLocation);
1108 s_fFirstCall = false;
1109 }
1110 return rc;
1111 }
1112 }
1113
1114 /*
1115 * Failed.
1116 */
1117 /* Pick the best error code. */
1118 for (uint32_t i = 0; rc == VERR_FILE_NOT_FOUND && i < RT_ELEMENTS(aKernels); i++)
1119 if (aKernels[i].rc != VERR_FILE_NOT_FOUND)
1120 rc = aKernels[i].rc;
1121
1122 /* Bitch about it. */
1123 printf("RTR0DbgKrnlInfoOpen: failed to find matching kernel file! rc=%d\n", rc);
1124 if (s_fFirstCall)
1125 {
1126 for (uint32_t i = 0; i < RT_ELEMENTS(aKernels); i++)
1127 printf("RTR0DbgKrnlInfoOpen: '%s' -> %d\n", aKernels[i].pszLocation, aKernels[i].rc);
1128 s_fFirstCall = false;
1129 }
1130
1131 return rc;
1132}
1133
1134
1135RTR0DECL(uint32_t) RTR0DbgKrnlInfoRetain(RTDBGKRNLINFO hKrnlInfo)
1136{
1137 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1138 AssertPtrReturn(pThis, UINT32_MAX);
1139 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
1140
1141 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
1142 Assert(cRefs && cRefs < 100000);
1143 return cRefs;
1144}
1145
1146
1147RTR0DECL(uint32_t) RTR0DbgKrnlInfoRelease(RTDBGKRNLINFO hKrnlInfo)
1148{
1149 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1150 if (pThis == NIL_RTDBGKRNLINFO)
1151 return 0;
1152 AssertPtrReturn(pThis, UINT32_MAX);
1153 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), UINT32_MAX);
1154
1155 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
1156 if (cRefs == 0)
1157 rtR0DbgKrnlDarwinDtor(pThis);
1158 return cRefs;
1159}
1160
1161
1162RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszStructure,
1163 const char *pszMember, size_t *poffMember)
1164{
1165 RTDBGKRNLINFOINT *pThis = hKrnlInfo;
1166 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
1167 AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
1168 AssertPtrReturn(pszMember, VERR_INVALID_POINTER);
1169 AssertPtrReturn(pszModule, VERR_INVALID_POINTER);
1170 AssertPtrReturn(pszStructure, VERR_INVALID_POINTER);
1171 AssertPtrReturn(poffMember, VERR_INVALID_POINTER);
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