VirtualBox

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

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

*: scm cleanup run.

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