VirtualBox

source: vbox/trunk/src/VBox/Runtime/include/internal/dbgmod.h@ 46113

Last change on this file since 46113 was 46113, checked in by vboxsync, 12 years ago

Implemented debug module that uses the exported symbols. This will work on all hosts. :-)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.5 KB
Line 
1/* $Id: dbgmod.h 46113 2013-05-15 22:39:43Z vboxsync $ */
2/** @file
3 * IPRT - Internal Header for RTDbgMod and the associated interpreters.
4 */
5
6/*
7 * Copyright (C) 2008-2012 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#ifndef ___internal_dbgmod_h
28#define ___internal_dbgmod_h
29
30#include <iprt/types.h>
31#include <iprt/critsect.h>
32#include <iprt/ldr.h> /* for PFNRTLDRENUMDBG */
33#include "internal/magics.h"
34
35RT_C_DECLS_BEGIN
36
37/** @addtogroup grp_rt_dbgmod
38 * @internal
39 * @{
40 */
41
42
43/** Pointer to the internal module structure. */
44typedef struct RTDBGMODINT *PRTDBGMODINT;
45
46/**
47 * Virtual method table for executable image interpreters.
48 */
49typedef struct RTDBGMODVTIMG
50{
51 /** Magic number (RTDBGMODVTIMG_MAGIC). */
52 uint32_t u32Magic;
53 /** Reserved. */
54 uint32_t fReserved;
55 /** The name of the interpreter. */
56 const char *pszName;
57
58 /**
59 * Try open the image.
60 *
61 * This combines probing and opening.
62 *
63 * @returns IPRT status code. No informational returns defined.
64 *
65 * @param pMod Pointer to the module that is being opened.
66 *
67 * The RTDBGMOD::pszDbgFile member will point to
68 * the filename of any debug info we're aware of
69 * on input. Also, or alternatively, it is expected
70 * that the interpreter will look for debug info in
71 * the executable image file when present and that it
72 * may ask the image interpreter for this when it's
73 * around.
74 *
75 * Upon successful return the method is expected to
76 * initialize pImgOps and pvImgPriv.
77 */
78 DECLCALLBACKMEMBER(int, pfnTryOpen)(PRTDBGMODINT pMod);
79
80 /**
81 * Close the interpreter, freeing all associated resources.
82 *
83 * The caller sets the pDbgOps and pvDbgPriv RTDBGMOD members
84 * to NULL upon return.
85 *
86 * @param pMod Pointer to the module structure.
87 */
88 DECLCALLBACKMEMBER(int, pfnClose)(PRTDBGMODINT pMod);
89
90 /**
91 * Enumerate the debug info contained in the executable image.
92 *
93 * Identical to RTLdrEnumDbgInfo.
94 *
95 * @returns IPRT status code or whatever pfnCallback returns.
96 *
97 * @param pMod Pointer to the module structure.
98 * @param pfnCallback The callback function. Ignore the module
99 * handle argument!
100 * @param pvUser The user argument.
101 */
102 DECLCALLBACKMEMBER(int, pfnEnumDbgInfo)(PRTDBGMODINT pMod, PFNRTLDRENUMDBG pfnCallback, void *pvUser);
103
104 /**
105 * Enumerate the segments in the executable image.
106 *
107 * Identical to RTLdrEnumSegments.
108 *
109 * @returns IPRT status code or whatever pfnCallback returns.
110 *
111 * @param pMod Pointer to the module structure.
112 * @param pfnCallback The callback function. Ignore the module
113 * handle argument!
114 * @param pvUser The user argument.
115 */
116 DECLCALLBACKMEMBER(int, pfnEnumSegments)(PRTDBGMODINT pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser);
117
118 /**
119 * Enumerates the symbols exported by the module.
120 *
121 * @returns iprt status code, which might have been returned by pfnCallback.
122 * @param pMod Pointer to the module structure.
123 * @param fFlags Flags indicating what to return and such.
124 * @param BaseAddress The image base addressto use when calculating the
125 * symbol values.
126 * @param pfnCallback The callback function which each symbol is to be fed
127 * to.
128 * @param pvUser User argument to pass to the enumerator.
129 */
130 DECLCALLBACKMEMBER(int, pfnEnumSymbols)(PRTDBGMODINT pMod, uint32_t fFlags, RTLDRADDR BaseAddress,
131 PFNRTLDRENUMSYMS pfnCallback, void *pvUser);
132
133 /**
134 * Gets the size of the loaded image.
135 *
136 * Identical to RTLdrSize.
137 *
138 * @returns The size in bytes, RTUINTPTR_MAX on failure.
139 *
140 * @param pMod Pointer to the module structure.
141 */
142 DECLCALLBACKMEMBER(RTUINTPTR, pfnImageSize)(PRTDBGMODINT pMod);
143
144 /**
145 * Converts a link address to a segment:offset address (RVA included).
146 *
147 * @returns IPRT status code.
148 *
149 * @param pMod Pointer to the module structure.
150 * @param LinkAddress The link address to convert.
151 * @param piSeg The segment index.
152 * @param poffSeg Where to return the segment offset.
153 */
154 DECLCALLBACKMEMBER(int, pfnLinkAddressToSegOffset)(PRTDBGMODINT pMod, RTLDRADDR LinkAddress,
155 PRTDBGSEGIDX piSeg, PRTLDRADDR poffSeg);
156
157 /**
158 * Creates a read-only mapping of a part of the image file.
159 *
160 * @returns IPRT status code and *ppvMap set on success.
161 *
162 * @param pMod Pointer to the module structure.
163 * @param off The offset into the image file.
164 * @param cb The number of bytes to map.
165 * @param ppvMap Where to return the mapping address on success.
166 */
167 DECLCALLBACKMEMBER(int, pfnMapPart)(PRTDBGMODINT pMod, RTFOFF off, size_t cb, void const **ppvMap);
168
169 /**
170 * Unmaps memory previously mapped by pfnMapPart.
171 *
172 * @returns IPRT status code, *ppvMap set to NULL on success.
173 *
174 * @param pMod Pointer to the module structure.
175 * @param cb The size of the mapping.
176 * @param ppvMap The mapping address on input, NULL on
177 * successful return.
178 */
179 DECLCALLBACKMEMBER(int, pfnUnmapPart)(PRTDBGMODINT pMod, size_t cb, void const **ppvMap);
180
181
182 /** For catching initialization errors (RTDBGMODVTIMG_MAGIC). */
183 uint32_t u32EndMagic;
184} RTDBGMODVTIMG;
185/** Pointer to a const RTDBGMODVTIMG. */
186typedef RTDBGMODVTIMG const *PCRTDBGMODVTIMG;
187
188
189/**
190 * Virtual method table for debug info interpreters.
191 */
192typedef struct RTDBGMODVTDBG
193{
194 /** Magic number (RTDBGMODVTDBG_MAGIC). */
195 uint32_t u32Magic;
196 /** Mask of supported debug info types, see grp_rt_dbg_type.
197 * Used to speed up the search for a suitable interpreter. */
198 uint32_t fSupports;
199 /** The name of the interpreter. */
200 const char *pszName;
201
202 /**
203 * Try open the image.
204 *
205 * This combines probing and opening.
206 *
207 * @returns IPRT status code. No informational returns defined.
208 *
209 * @param pMod Pointer to the module that is being opened.
210 *
211 * The RTDBGMOD::pszDbgFile member will point to
212 * the filename of any debug info we're aware of
213 * on input. Also, or alternatively, it is expected
214 * that the interpreter will look for debug info in
215 * the executable image file when present and that it
216 * may ask the image interpreter for this when it's
217 * around.
218 *
219 * Upon successful return the method is expected to
220 * initialize pDbgOps and pvDbgPriv.
221 */
222 DECLCALLBACKMEMBER(int, pfnTryOpen)(PRTDBGMODINT pMod);
223
224 /**
225 * Close the interpreter, freeing all associated resources.
226 *
227 * The caller sets the pDbgOps and pvDbgPriv RTDBGMOD members
228 * to NULL upon return.
229 *
230 * @param pMod Pointer to the module structure.
231 */
232 DECLCALLBACKMEMBER(int, pfnClose)(PRTDBGMODINT pMod);
233
234
235
236 /**
237 * Converts an image relative virtual address address to a segmented address.
238 *
239 * @returns Segment index on success, NIL_RTDBGSEGIDX on failure.
240 * @param pMod Pointer to the module structure.
241 * @param uRva The image relative address to convert.
242 * @param poffSeg Where to return the segment offset. Optional.
243 */
244 DECLCALLBACKMEMBER(RTDBGSEGIDX, pfnRvaToSegOff)(PRTDBGMODINT pMod, RTUINTPTR uRva, PRTUINTPTR poffSeg);
245
246 /**
247 * Image size when mapped if segments are mapped adjacently.
248 *
249 * For ELF, PE, and Mach-O images this is (usually) a natural query, for LX and
250 * NE and such it's a bit odder and the answer may not make much sense for them.
251 *
252 * @returns Image mapped size.
253 * @param pMod Pointer to the module structure.
254 */
255 DECLCALLBACKMEMBER(RTUINTPTR, pfnImageSize)(PRTDBGMODINT pMod);
256
257
258
259 /**
260 * Adds a segment to the module (optional).
261 *
262 * @returns IPRT status code.
263 * @retval VERR_NOT_SUPPORTED if the interpreter doesn't support this feature.
264 * @retval VERR_DBG_SEGMENT_INDEX_CONFLICT if the segment index exists already.
265 *
266 * @param pMod Pointer to the module structure.
267 * @param uRva The segment image relative address.
268 * @param cb The segment size.
269 * @param pszName The segment name.
270 * @param cchName The length of the segment name.
271 * @param fFlags Segment flags.
272 * @param piSeg The segment index or NIL_RTDBGSEGIDX on input.
273 * The assigned segment index on successful return.
274 * Optional.
275 */
276 DECLCALLBACKMEMBER(int, pfnSegmentAdd)(PRTDBGMODINT pMod, RTUINTPTR uRva, RTUINTPTR cb, const char *pszName, size_t cchName,
277 uint32_t fFlags, PRTDBGSEGIDX piSeg);
278
279 /**
280 * Gets the segment count.
281 *
282 * @returns Number of segments.
283 * @retval NIL_RTDBGSEGIDX if unknown.
284 *
285 * @param pMod Pointer to the module structure.
286 */
287 DECLCALLBACKMEMBER(RTDBGSEGIDX, pfnSegmentCount)(PRTDBGMODINT pMod);
288
289 /**
290 * Gets information about a segment.
291 *
292 * @returns IPRT status code.
293 * @retval VERR_DBG_INVALID_SEGMENT_INDEX if iSeg is too high.
294 *
295 * @param pMod Pointer to the module structure.
296 * @param iSeg The segment.
297 * @param pSegInfo Where to store the segment information.
298 */
299 DECLCALLBACKMEMBER(int, pfnSegmentByIndex)(PRTDBGMODINT pMod, RTDBGSEGIDX iSeg, PRTDBGSEGMENT pSegInfo);
300
301
302
303 /**
304 * Adds a symbol to the module (optional).
305 *
306 * @returns IPRT code.
307 * @retval VERR_NOT_SUPPORTED if the interpreter doesn't support this feature.
308 *
309 * @param pMod Pointer to the module structure.
310 * @param pszSymbol The symbol name.
311 * @param cchSymbol The length for the symbol name.
312 * @param iSeg The segment number (0-based). RTDBGMOD_SEG_RVA can be used.
313 * @param off The offset into the segment.
314 * @param cb The area covered by the symbol. 0 is fine.
315 * @param fFlags Flags.
316 * @param piOrdinal Where to return the symbol ordinal on success. If the
317 * interpreter doesn't do ordinals, this will be set to
318 * UINT32_MAX. Optional
319 */
320 DECLCALLBACKMEMBER(int, pfnSymbolAdd)(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol,
321 uint32_t iSeg, RTUINTPTR off, RTUINTPTR cb, uint32_t fFlags,
322 uint32_t *piOrdinal);
323
324 /**
325 * Gets the number of symbols in the module.
326 *
327 * This is used for figuring out the max value to pass to pfnSymbolByIndex among
328 * other things.
329 *
330 * @returns The number of symbols, UINT32_MAX if not known/supported.
331 *
332 * @param pMod Pointer to the module structure.
333 */
334 DECLCALLBACKMEMBER(uint32_t, pfnSymbolCount)(PRTDBGMODINT pMod);
335
336 /**
337 * Queries symbol information by ordinal number.
338 *
339 * @returns IPRT status code.
340 * @retval VINF_SUCCESS on success, no informational status code.
341 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
342 * @retval VERR_NOT_SUPPORTED if lookup by ordinal is not supported.
343 * @retval VERR_SYMBOL_NOT_FOUND if there is no symbol at that index.
344 *
345 * @param pMod Pointer to the module structure.
346 * @param iOrdinal The symbol ordinal number.
347 * @param pSymInfo Where to store the symbol information.
348 */
349 DECLCALLBACKMEMBER(int, pfnSymbolByOrdinal)(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGSYMBOL pSymInfo);
350
351 /**
352 * Queries symbol information by symbol name.
353 *
354 * @returns IPRT status code.
355 * @retval VINF_SUCCESS on success, no informational status code.
356 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
357 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
358 *
359 * @param pMod Pointer to the module structure.
360 * @param pszSymbol The symbol name.
361 * @param cchSymbol The length of the symbol name.
362 * @param pSymInfo Where to store the symbol information.
363 */
364 DECLCALLBACKMEMBER(int, pfnSymbolByName)(PRTDBGMODINT pMod, const char *pszSymbol, size_t cchSymbol, PRTDBGSYMBOL pSymInfo);
365
366 /**
367 * Queries symbol information by address.
368 *
369 * The returned symbol is what the debug info interpreter considers the symbol
370 * most applicable to the specified address. This usually means a symbol with an
371 * address equal or lower than the requested.
372 *
373 * @returns IPRT status code.
374 * @retval VINF_SUCCESS on success, no informational status code.
375 * @retval VERR_DBG_NO_SYMBOLS if there aren't any symbols.
376 * @retval VERR_SYMBOL_NOT_FOUND if no suitable symbol was found.
377 *
378 * @param pMod Pointer to the module structure.
379 * @param iSeg The segment number (0-based) or RTDBGSEGIDX_ABS.
380 * @param off The offset into the segment.
381 * @param fFlags Symbol search flags, see RTDBGSYMADDR_FLAGS_XXX.
382 * @param poffDisp Where to store the distance between the specified address
383 * and the returned symbol. Optional.
384 * @param pSymInfo Where to store the symbol information.
385 */
386 DECLCALLBACKMEMBER(int, pfnSymbolByAddr)(PRTDBGMODINT pMod, uint32_t iSeg, RTUINTPTR off, uint32_t fFlags,
387 PRTINTPTR poffDisp, PRTDBGSYMBOL pSymInfo);
388
389
390
391 /**
392 * Adds a line number to the module (optional).
393 *
394 * @returns IPRT status code.
395 * @retval VERR_NOT_SUPPORTED if the interpreter doesn't support this feature.
396 *
397 * @param pMod Pointer to the module structure.
398 * @param pszFile The filename.
399 * @param cchFile The length of the filename.
400 * @param uLineNo The line number.
401 * @param iSeg The segment number (0-based).
402 * @param off The offset into the segment.
403 * @param piOrdinal Where to return the line number ordinal on success. If
404 * the interpreter doesn't do ordinals, this will be set to
405 * UINT32_MAX. Optional
406 */
407 DECLCALLBACKMEMBER(int, pfnLineAdd)(PRTDBGMODINT pMod, const char *pszFile, size_t cchFile, uint32_t uLineNo,
408 uint32_t iSeg, RTUINTPTR off, uint32_t *piOrdinal);
409
410 /**
411 * Gets the number of line numbers in the module.
412 *
413 * @returns The number or UINT32_MAX if not known/supported.
414 *
415 * @param pMod Pointer to the module structure.
416 */
417 DECLCALLBACKMEMBER(uint32_t, pfnLineCount)(PRTDBGMODINT pMod);
418
419 /**
420 * Queries line number information by ordinal number.
421 *
422 * @returns IPRT status code.
423 * @retval VINF_SUCCESS on success, no informational status code.
424 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
425 * @retval VERR_DBG_LINE_NOT_FOUND if there is no line number with that
426 * ordinal.
427 *
428 * @param pMod Pointer to the module structure.
429 * @param iOrdinal The line number ordinal number.
430 * @param pLineInfo Where to store the information about the line number.
431 */
432 DECLCALLBACKMEMBER(int, pfnLineByOrdinal)(PRTDBGMODINT pMod, uint32_t iOrdinal, PRTDBGLINE pLineInfo);
433
434 /**
435 * Queries line number information by address.
436 *
437 * @returns IPRT status code.
438 * @retval VINF_SUCCESS on success, no informational status code.
439 * @retval VERR_DBG_NO_LINE_NUMBERS if there aren't any line numbers.
440 * @retval VERR_DBG_LINE_NOT_FOUND if no suitable line number was found.
441 *
442 * @param pMod Pointer to the module structure.
443 * @param iSeg The segment number (0-based) or RTDBGSEGIDX_ABS.
444 * @param off The offset into the segment.
445 * @param poffDisp Where to store the distance between the specified address
446 * and the returned line number. Optional.
447 * @param pLineInfo Where to store the information about the closest line
448 * number.
449 */
450 DECLCALLBACKMEMBER(int, pfnLineByAddr)(PRTDBGMODINT pMod, uint32_t iSeg, RTUINTPTR off, PRTINTPTR poffDisp, PRTDBGLINE pLineInfo);
451
452
453 /** For catching initialization errors (RTDBGMODVTDBG_MAGIC). */
454 uint32_t u32EndMagic;
455} RTDBGMODVTDBG;
456/** Pointer to a const RTDBGMODVTDBG. */
457typedef RTDBGMODVTDBG const *PCRTDBGMODVTDBG;
458
459
460/**
461 * Deferred loading callback.
462 *
463 * @returns IPRT status code. On success the necessary method tables should be
464 * installed in @a pMod.
465 * @param pMod Pointer to the debug module structure.
466 * @param pDeferred The deferred load data.
467 */
468typedef DECLCALLBACK(int) FNRTDBGMODDEFERRED(PRTDBGMODINT pMod, struct RTDBGMODDEFERRED *pDeferred);
469/** Pointer to a deferred loading callback. */
470typedef FNRTDBGMODDEFERRED *PFNRTDBGMODDEFERRED;
471
472
473/**
474 * Structure pointed to by pvDbgPriv and/or pvImgPriv when
475 * g_rtDbgModVtDbgDeferred and/or g_rtDbgModVtImgDeferred are being used.
476 */
477typedef struct RTDBGMODDEFERRED
478{
479 /** The image size.
480 * Deferred loading is almost pointless without knowing the module size, as
481 * it cannot be mapped (correctly) without it. */
482 RTUINTPTR cbImage;
483 /** Reference counter. */
484 uint32_t volatile cRefs;
485 /** The configuration instance (referenced), can be NIL. */
486 RTDBGCFG hDbgCfg;
487 /** Performs deferred loading of the module. */
488 PFNRTDBGMODDEFERRED pfnDeferred;
489 /** Callback specific data. */
490 union
491 {
492 struct
493 {
494 /** The time/date stamp of the executable image and codeview file. */
495 uint32_t uTimestamp;
496 } PeImage,
497 OldCodeView;
498
499 struct
500 {
501 /** The PDB uuid. */
502 RTUUID Uuid;
503 /** The PDB age. */
504 uint32_t uAge;
505 } NewCodeview;
506
507 struct
508 {
509 /** The CRC-32 value found in the .gnu_debuglink section. */
510 uint32_t uCrc32;
511 } GnuDebugLink;
512 } u;
513} RTDBGMODDEFERRED;
514/** Pointer to the deferred loading data. */
515typedef RTDBGMODDEFERRED *PRTDBGMODDEFERRED;
516
517
518/**
519 * Debug module structure.
520 */
521typedef struct RTDBGMODINT
522{
523 /** Magic value (RTDBGMOD_MAGIC). */
524 uint32_t u32Magic;
525 /** The number of reference there are to this module.
526 * This is used to perform automatic cleanup and sharing. */
527 uint32_t volatile cRefs;
528 /** The module tag. */
529 uint64_t uTag;
530
531 /** When set, the loading of the image and debug info (including locating any
532 * external files), will not have taken place yet. */
533 uint32_t fDeferred : 1;
534 /** Set if deferred loading failed. */
535 uint32_t fDeferredFailed : 1;
536 /** Set if the debug info is based on image exports and segments. */
537 uint32_t fExports : 1;
538 /** Alignment padding. */
539 uint32_t fPadding1 : 29;
540#if ARCH_BITS == 64
541 uint32_t u32Padding2;
542#endif
543
544 /** The module name (short). */
545 char const *pszName;
546 /** The image file specified by the user. Can be NULL. */
547 char const *pszImgFileSpecified;
548 /** The module filename. Can be NULL. */
549 char const *pszImgFile;
550 /** The debug info file (if external). Can be NULL. */
551 char const *pszDbgFile;
552
553 /** The method table for the executable image interpreter. */
554 PCRTDBGMODVTIMG pImgVt;
555 /** Pointer to the private data of the executable image interpreter. */
556 void *pvImgPriv;
557
558 /** The method table for the debug info interpreter. */
559 PCRTDBGMODVTDBG pDbgVt;
560 /** Pointer to the private data of the debug info interpreter. */
561 void *pvDbgPriv;
562
563 /** Critical section serializing access to the module. */
564 RTCRITSECT CritSect;
565} RTDBGMODINT;
566/** Pointer to an debug module structure. */
567typedef RTDBGMODINT *PRTDBGMODINT;
568
569
570extern DECLHIDDEN(RTSTRCACHE) g_hDbgModStrCache;
571extern DECLHIDDEN(RTDBGMODVTDBG const) g_rtDbgModVtDbgDwarf;
572extern DECLHIDDEN(RTDBGMODVTDBG const) g_rtDbgModVtDbgNm;
573#ifdef RT_OS_WINDOWS
574extern DECLHIDDEN(RTDBGMODVTDBG const) g_rtDbgModVtDbgDbgHelp;
575#endif
576extern DECLHIDDEN(RTDBGMODVTDBG const) g_rtDbgModVtDbgDeferred;
577
578extern DECLHIDDEN(RTDBGMODVTIMG const) g_rtDbgModVtImgLdr;
579extern DECLHIDDEN(RTDBGMODVTIMG const) g_rtDbgModVtImgDeferred;
580
581DECLHIDDEN(int) rtDbgModContainerCreate(PRTDBGMODINT pMod, RTUINTPTR cbSeg);
582DECLHIDDEN(int) rtDbgModCreateForExports(PRTDBGMODINT pDbgMod);
583DECLHIDDEN(int) rtDbgModDeferredCreate(PRTDBGMODINT pDbgMod, PFNRTDBGMODDEFERRED pfnDeferred, RTUINTPTR cbImage,
584 RTDBGCFG hDbgCfg, PRTDBGMODDEFERRED *ppDeferred);
585
586DECLHIDDEN(int) rtDbgModLdrOpenFromHandle(PRTDBGMODINT pDbgMod, RTLDRMOD hLdrMod);
587
588/** @} */
589
590RT_C_DECLS_END
591
592#endif
593
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