tkMacOSXDebug.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:18k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * tkMacOSXDebug.c --
  3.  *
  4.  * Implementation of Macintosh specific functions for debugging MacOS events,
  5.  * regions, etc...
  6.  *
  7.  * Copyright 2001, Apple Computer, Inc.
  8.  * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net>
  9.  *
  10.  * See the file "license.terms" for information on usage and redistribution of
  11.  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
  12.  *
  13.  * The following terms apply to all files originating from Apple
  14.  * Computer, Inc. ("Apple") and associated with the software
  15.  * unless explicitly disclaimed in individual files.
  16.  *
  17.  *
  18.  * Apple hereby grants permission to use, copy, modify,
  19.  * distribute, and license this software and its documentation
  20.  * for any purpose, provided that existing copyright notices are
  21.  * retained in all copies and that this notice is included
  22.  * verbatim in any distributions. No written agreement, license,
  23.  * or royalty fee is required for any of the authorized
  24.  * uses. Modifications to this software may be copyrighted by
  25.  * their authors and need not follow the licensing terms
  26.  * described here, provided that the new terms are clearly
  27.  * indicated on the first page of each file where they apply.
  28.  *
  29.  *
  30.  * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE
  31.  * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
  32.  * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
  33.  * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF,
  34.  * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE
  35.  * POSSIBILITY OF SUCH DAMAGE.  APPLE, THE AUTHORS AND
  36.  * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
  37.  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  38.  * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.  THIS
  39.  * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE
  40.  * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE
  41.  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  42.  *
  43.  * GOVERNMENT USE: If you are acquiring this software on behalf
  44.  * of the U.S. government, the Government shall have only
  45.  * "Restricted Rights" in the software and related documentation
  46.  * as defined in the Federal Acquisition Regulations (FARs) in
  47.  * Clause 52.227.19 (c) (2).  If you are acquiring the software
  48.  * on behalf of the Department of Defense, the software shall be
  49.  * classified as "Commercial Computer Software" and the
  50.  * Government shall have only "Restricted Rights" as defined in
  51.  * Clause 252.227-7013 (c) (1) of DFARs.  Notwithstanding the
  52.  * foregoing, the authors grant the U.S. Government and others
  53.  * acting in its behalf permission to use and distribute the
  54.  * software in accordance with the terms specified in this
  55.  * license.
  56.  *
  57.  * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.2.2.14 2007/11/09 06:26:55 das Exp $
  58.  */
  59. #include "tkMacOSXPrivate.h"
  60. #include "tkMacOSXDebug.h"
  61. #ifdef TK_MAC_DEBUG
  62. typedef struct {
  63.     EventKind kind;
  64.     const char * name;
  65. } MyEventName;
  66. typedef struct {
  67.     EventClass c;
  68.     MyEventName * names;
  69. } MyEventNameList;
  70. static MyEventName windowEventNames [] = {
  71.  {  kEventWindowUpdate,"Update"},
  72.  {  kEventWindowDrawContent,"DrawContent"},
  73.  {  kEventWindowActivated,"Activated"},
  74.  {  kEventWindowDeactivated,"Deactivated"},
  75.  {  kEventWindowGetClickActivation,"GetClickActivation"},
  76.  {  kEventWindowShowing,"Showing"},
  77.  {  kEventWindowHiding,"Hiding"},
  78.  {  kEventWindowShown,"Shown"},
  79.  {  kEventWindowHidden,"Hidden"},
  80.  {  kEventWindowBoundsChanging,"BoundsChanging"},
  81.  {  kEventWindowBoundsChanged,"BoundsChanged"},
  82.  {  kEventWindowResizeStarted,"ResizeStarted"},
  83.  {  kEventWindowResizeCompleted,"ResizeCompleted"},
  84.  {  kEventWindowDragStarted,"DragStarted"},
  85.  {  kEventWindowDragCompleted,"DragCompleted"},
  86.  {  kEventWindowClickDragRgn,"ClickDragRgn"},
  87.  {  kEventWindowClickResizeRgn,"ClickResizeRgn"},
  88.  {  kEventWindowClickCollapseRgn,"ClickCollapseRgn"},
  89.  {  kEventWindowClickCloseRgn,"ClickCloseRgn"},
  90.  {  kEventWindowClickZoomRgn,"ClickZoomRgn"},
  91.  {  kEventWindowClickContentRgn,"ClickContentRgn"},
  92.  {  kEventWindowClickProxyIconRgn,"ClickProxyIconRgn"},
  93.  {  kEventWindowCursorChange,"CursorChange" },
  94.  {  kEventWindowCollapse,"Collapse"},
  95.  {  kEventWindowCollapsed,"Collapsed"},
  96.  {  kEventWindowCollapseAll,"CollapseAll"},
  97.  {  kEventWindowExpand,"Expand"},
  98.  {  kEventWindowExpanded,"Expanded"},
  99.  {  kEventWindowExpandAll,"ExpandAll"},
  100.  {  kEventWindowCollapse,"Collapse"},
  101.  {  kEventWindowClose,"Close"},
  102.  {  kEventWindowClosed,"Closed"},
  103.  {  kEventWindowCloseAll,"CloseAll"},
  104.  {  kEventWindowZoom,"Zoom"},
  105.  {  kEventWindowZoomed,"Zoomed"},
  106.  {  kEventWindowZoomAll,"ZoomAll"},
  107.  {  kEventWindowContextualMenuSelect,"ContextualMenuSelect"},
  108.  {  kEventWindowPathSelect,"PathSelect"},
  109.  {  kEventWindowGetIdealSize,"GetIdealSize"},
  110.  {  kEventWindowGetMinimumSize,"GetMinimumSize"},
  111.  {  kEventWindowGetMaximumSize,"GetMaximumSize"},
  112.  {  kEventWindowConstrain,"Constrain"},
  113.  {  kEventWindowHandleContentClick,"HandleContentClick"},
  114.  {  kEventWindowProxyBeginDrag,"ProxyBeginDra}"},
  115.  {  kEventWindowProxyEndDrag,"ProxyEndDrag"},
  116.  {  kEventWindowFocusAcquired,"FocusAcquired"},
  117.  {  kEventWindowFocusRelinquish,"FocusRelinquish"},
  118.  {  kEventWindowDrawFrame,"DrawFrame"},
  119.  {  kEventWindowDrawPart,"DrawPart"},
  120.  {  kEventWindowGetRegion,"GetRegion"},
  121.  {  kEventWindowHitTest,"HitTest"},
  122.  {  kEventWindowInit,"Init"},
  123.  {  kEventWindowDispose,"Dispose"},
  124.  {  kEventWindowDragHilite,"DragHilite"},
  125.  {  kEventWindowModified,"Modified"},
  126.  {  kEventWindowSetupProxyDragImage,"SetupProxyDragImage"},
  127.  {  kEventWindowStateChanged,"StateChanged"},
  128.  {  kEventWindowMeasureTitle,"MeasureTitle"},
  129.  {  kEventWindowDrawGrowBox,"DrawGrowBox"},
  130.  {  kEventWindowGetGrowImageRegion,"GetGrowImageRegion"},
  131.  {  kEventWindowPaint,"Paint"},
  132.  { 0, NULL },
  133. };
  134. static MyEventName mouseEventNames [] = {
  135.  {  kEventMouseMoved, "Moved"},
  136.  {  kEventMouseUp, "Up"},
  137.  {  kEventMouseDown, "Down"},
  138.  {  kEventMouseDragged, "Dragged"},
  139.  {  kEventMouseWheelMoved, "WheelMoved"},
  140.  { 0, NULL}
  141. };
  142. static MyEventName keyboardEventNames [] = {
  143.  { kEventRawKeyDown, "Down"},
  144.  { kEventRawKeyRepeat, "Repeat"},
  145.  { kEventRawKeyUp, "Up"},
  146.  { kEventRawKeyModifiersChanged, "ModifiersChanged"},
  147.  { kEventHotKeyPressed, "HotKeyPressed"},
  148.  { kEventHotKeyReleased, "HotKeyReleased"},
  149.  { 0, NULL}
  150. };
  151. static MyEventName appEventNames [] = {
  152.  { kEventAppActivated, "Activated"},
  153.  { kEventAppDeactivated, "Deactivated"},
  154.  { kEventAppQuit, "Quit"},
  155.  { kEventAppLaunchNotification, "LaunchNotification"},
  156.  { kEventAppLaunched, "Launched"},
  157.  { kEventAppTerminated, "Terminated"},
  158.  { kEventAppFrontSwitched, "FrontSwitched"},
  159.  { 0, NULL}
  160. };
  161. static MyEventName menuEventNames [] = {
  162.  { kEventMenuBeginTracking, "BeginTracking"},
  163.  { kEventMenuEndTracking, "EndTracking"},
  164.  { kEventMenuChangeTrackingMode, "ChangeTrackingMode"},
  165.  { kEventMenuOpening, "Opening"},
  166.  { kEventMenuClosed, "Closed"},
  167.  { kEventMenuTargetItem, "TargetItem"},
  168.  { kEventMenuMatchKey, "MatchKey"},
  169.  { kEventMenuEnableItems, "EnableItems"},
  170.  { kEventMenuDispose, "Dispose"},
  171.  { 0, NULL }
  172. };
  173. static MyEventName controlEventNames [] = {
  174.  { kEventControlInitialize, "Initialize" },
  175.  { kEventControlDispose, "Dispose" },
  176.  { kEventControlGetOptimalBounds, "GetOptimalBounds" },
  177.  { kEventControlHit, "Hit" },
  178.  { kEventControlSimulateHit, "SimulateHit" },
  179.  { kEventControlHitTest, "HitTest" },
  180.  { kEventControlDraw, "Draw" },
  181.  { kEventControlApplyBackground, "ApplyBackground" },
  182.  { kEventControlApplyTextColor, "ApplyTextColor" },
  183.  { kEventControlSetFocusPart, "SetFocusPart" },
  184.  { kEventControlGetFocusPart, "GetFocusPart" },
  185.  { kEventControlActivate, "Activate" },
  186.  { kEventControlDeactivate, "Deactivate" },
  187.  { kEventControlSetCursor, "SetCursor" },
  188.  { kEventControlContextualMenuClick, "ContextualMenuClick" },
  189.  { kEventControlClick, "Click" },
  190.  { kEventControlTrack, "Track" },
  191.  { kEventControlGetScrollToHereStartPoint, "GetScrollToHereStartPoint" },
  192.  { kEventControlGetIndicatorDragConstraint, "GetIndicatorDragConstraint" },
  193.  { kEventControlIndicatorMoved, "IndicatorMoved" },
  194.  { kEventControlGhostingFinished, "GhostingFinished" },
  195.  { kEventControlGetActionProcPart, "GetActionProcPart" },
  196.  { kEventControlGetPartRegion, "GetPartRegion" },
  197.  { kEventControlGetPartBounds, "GetPartBounds" },
  198.  { kEventControlSetData, "SetData" },
  199.  { kEventControlGetData, "GetData" },
  200.  { kEventControlValueFieldChanged, "ValueFieldChanged" },
  201.  { kEventControlAddedSubControl, "AddedSubControl" },
  202.  { kEventControlRemovingSubControl, "RemovingSubControl" },
  203.  { kEventControlBoundsChanged, "BoundsChanged" },
  204.  { kEventControlOwningWindowChanged, "OwningWindowChanged" },
  205.  { kEventControlArbitraryMessage, "ArbitraryMessage" },
  206.  { 0, NULL }
  207. };
  208. static MyEventName commandEventNames [] = {
  209.  { kEventCommandProcess, "Process" },
  210.  { kEventCommandUpdateStatus, "UpdateStatus" },
  211.  { 0, NULL }
  212. };
  213. static MyEventNameList eventNameList [] = {
  214.  { kEventClassWindow, windowEventNames },
  215.  { kEventClassMouse, mouseEventNames },
  216.  { kEventClassKeyboard, keyboardEventNames },
  217.  { kEventClassApplication, appEventNames },
  218.  { kEventClassMenu, menuEventNames },
  219.  { kEventClassControl, controlEventNames },
  220.  { kEventClassCommand, commandEventNames },
  221.  { 0, NULL}
  222. };
  223. #ifdef TK_MACOSXDEBUG_UNUSED
  224. static MyEventName classicEventNames [] = {
  225.  { nullEvent,"nullEvent" },
  226.  { mouseDown,"mouseDown" },
  227.  { mouseUp,"mouseUp" },
  228.  { keyDown,"keyDown" },
  229.  { keyUp,"keyUp" },
  230.  { autoKey,"autoKey" },
  231.  { updateEvt,"updateEvt" },
  232.  { diskEvt,"diskEvt" },
  233.  { activateEvt,"activateEvt" },
  234.  { osEvt,"osEvt" },
  235.  { kHighLevelEvent,"kHighLevelEvent" },
  236.  { 0, NULL }
  237. };
  238. #endif /* TK_MACOSXDEBUG_UNUSED */
  239. MODULE_SCOPE char *
  240. TkMacOSXCarbonEventToAscii(EventRef eventRef)
  241. {
  242.     EventClass eventClass;
  243.     EventKind eventKind;
  244.     MyEventNameList * list = eventNameList;
  245.     MyEventName * names = NULL;
  246.     static char str[256];
  247.     char *buf = str;
  248.     int *iPtr = (int*)str;
  249.     int found = 0;
  250.     eventClass = GetEventClass(eventRef);
  251.     eventKind = GetEventKind(eventRef);
  252.     *iPtr = eventClass;
  253.     buf[4] = 0;
  254.     strcat(buf, " ");
  255.     buf += strlen(buf);
  256.     while (list->names && (!names) ) {
  257. if (eventClass == list->c) {
  258.     names = list -> names;
  259. } else {
  260.     list++;
  261. }
  262.     }
  263.    while (names && names->name) {
  264.        if (eventKind == names->kind) {
  265.    snprintf(buf, 250, "%-20s", names->name);
  266.    break;
  267.        } else {
  268.    names++;
  269.        }
  270.     }
  271.     if (!found) {
  272. snprintf(buf, 250, "%-20d", eventKind);
  273.     }
  274.     return str;
  275. }
  276. #ifdef TK_MACOSXDEBUG_UNUSED
  277. MODULE_SCOPE char *
  278. TkMacOSXCarbonEventKindToAscii(EventRef eventRef, char * buf )
  279. {
  280.    EventClass eventClass;
  281.    EventKind  eventKind;
  282.    MyEventNameList * list = eventNameList;
  283.    MyEventName    * names = NULL;
  284.    int      found = 0;
  285.    eventClass = GetEventClass(eventRef);
  286.    eventKind = GetEventKind(eventRef);
  287.    while (list->names && (!names) ) {
  288.        if (eventClass == list -> c) {
  289.    names = list -> names;
  290.        } else {
  291.    list++;
  292.        }
  293.    }
  294.    if (names) {
  295.        found = 0;
  296.        while ( names->name && !found ) {
  297.    if (eventKind == names->kind) {
  298.        sprintf(buf,"%s",names->name);
  299.        found = 1;
  300.    } else {
  301.        names++;
  302.    }
  303.        }
  304.     }
  305.     if (!found) {
  306. sprintf ( buf,"%d", eventKind );
  307.      } else {
  308. sprintf ( buf,"%d", eventKind );
  309.      }
  310.      return buf;
  311. }
  312. MODULE_SCOPE char *
  313. TkMacOSXClassicEventToAscii(EventRecord * eventPtr, char * buf )
  314. {
  315.     MyEventName     * names = NULL;
  316.     int found = 0;
  317.     names = classicEventNames;
  318.     while ( names -> name && !found )
  319. if (eventPtr->what == names->kind) {
  320.     int * iPtr;
  321.     char cBuf[8];
  322.     iPtr=(int *) &cBuf;
  323.     *iPtr = eventPtr->message;
  324.     cBuf[4] = 0;
  325.     sprintf(buf, "%-16s %08x %04x %s", names->name,
  326.     (int) eventPtr->message,
  327.     eventPtr->modifiers,
  328.     cBuf);
  329.     found = 1;
  330. } else {
  331.   names++;
  332. }
  333.     if (!found) {
  334.        sprintf(buf,"%-16d %08x %08x, %s",
  335.        eventPtr->what, (int) eventPtr->message,
  336.        eventPtr->modifiers, buf);
  337.     }
  338.     return buf;
  339. }
  340. MODULE_SCOPE void
  341. TkMacOSXPrintPoint(char * tag, Point * p )
  342. {
  343.     TkMacOSXDbgMsg("%s %4d %4d", tag,p->h,p->v );
  344. }
  345. MODULE_SCOPE void
  346. TkMacOSXPrintRect(char * tag, Rect * r )
  347. {
  348.     TkMacOSXDbgMsg("%s %4d %4d %4d %4d (%dx%d)",
  349. tag, r->left, r->top, r->right, r->bottom,
  350. r->right - r->left + 1, r->bottom - r->top + 1);
  351. }
  352. MODULE_SCOPE void
  353. TkMacOSXPrintRegion(char * tag, RgnHandle rgn )
  354. {
  355.     Rect r;
  356.     GetRegionBounds(rgn,&r);
  357.     TkMacOSXPrintRect(tag,&r);
  358. }
  359. MODULE_SCOPE void
  360. TkMacOSXPrintWindowTitle(char * tag, WindowRef window )
  361. {
  362.     Str255 title;
  363.     GetWTitle(window,title);
  364.     title [title[0] + 1] = 0;
  365.     TkMacOSXDbgMsg("%s %s", tag, title +1 );
  366. }
  367. typedef struct {
  368.  int msg;
  369.  char * name;
  370. } MsgName;
  371. static MsgName msgNames [] = {
  372.     { kMenuDrawMsg,   "Draw"},
  373.     { kMenuSizeMsg,   "Size"},
  374.     { kMenuPopUpMsg,   "PopUp"},
  375.     { kMenuCalcItemMsg,   "CalcItem" },
  376.     { kMenuThemeSavvyMsg, "ThemeSavvy"},
  377.     { kMenuInitMsg,   "Init" },
  378.     { kMenuDisposeMsg,   "Dispose" },
  379.     { kMenuFindItemMsg,   "FindItem" },
  380.     { kMenuHiliteItemMsg, "HiliteItem" },
  381.     { kMenuDrawItemsMsg,  "DrawItems" },
  382.     { -1, NULL }
  383. };
  384. MODULE_SCOPE char *
  385. TkMacOSXMenuMessageToAscii(int msg, char * s)
  386. {
  387.     MsgName * msgNamePtr;
  388.     for (msgNamePtr = msgNames;msgNamePtr->name;) {
  389. if (msgNamePtr->msg == msg) {
  390.    strcpy(s,msgNamePtr->name);
  391.    return s;
  392. } else {
  393.     msgNamePtr++;
  394. }
  395.     }
  396.     sprintf(s,"unknown : %d", msg );
  397.     return s;
  398. }
  399. static MsgName trackingNames [] = {
  400.     { kMouseTrackingMousePressed  , "MousePressed  " },
  401.     { kMouseTrackingMouseReleased , "MouseReleased " },
  402.     { kMouseTrackingMouseExited   , "MouseExited   " },
  403.     { kMouseTrackingMouseEntered  , "MouseEntered  " },
  404.     { kMouseTrackingMouseMoved   , "MouseMoved    " },
  405.     { kMouseTrackingKeyModifiersChanged, "KeyModifiersChanged" },
  406.     { kMouseTrackingUserCancelled , "UserCancelled " },
  407.     { kMouseTrackingTimedOut   , "TimedOut    " },
  408.     { -1, NULL }
  409. };
  410. MODULE_SCOPE char *
  411. TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf)
  412. {
  413.     MsgName * namePtr;
  414.     for (namePtr = trackingNames; namePtr->name; namePtr++) {
  415. if (namePtr->msg == r) {
  416.     strcpy(buf, namePtr->name);
  417.     return buf;
  418. }
  419.     }
  420.     sprintf(buf, "Unknown mouse tracking result : %d", r);
  421.     return buf;
  422. }
  423. #endif /* TK_MACOSXDEBUG_UNUSED */
  424. MODULE_SCOPE void
  425. TkMacOSXDebugFlashRegion(
  426.     Drawable d,
  427.     HIShapeRef rgn)
  428. {
  429.     TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion,
  430.     CGrafPtr port, RgnHandle region);
  431.     CFShow(rgn);
  432.     if (d && rgn && QDDebugFlashRegion && !HIShapeIsEmpty(rgn)) {
  433. CGrafPtr port = TkMacOSXGetDrawablePort(d);
  434. if (port) {
  435.     static RgnHandle qdRgn = NULL;
  436.     if (!qdRgn) {
  437. qdRgn = NewRgn();
  438.     }
  439.     ChkErr(HIShapeGetAsQDRgn, rgn, qdRgn);
  440.     /*
  441.      * Carbon-internal region flashing SPI (c.f. Technote 2124)
  442.      */
  443.     QDDebugFlashRegion(port, qdRgn);
  444.     SetEmptyRgn(qdRgn);
  445. }
  446.     }
  447. }
  448. #endif /* TK_MAC_DEBUG */
  449. #include <mach-o/dyld.h>
  450. #include <mach-o/nlist.h>
  451. /*
  452.  *----------------------------------------------------------------------
  453.  *
  454.  * TkMacOSXGetNamedDebugSymbol --
  455.  *
  456.  *
  457.  * Dynamically acquire address of a named symbol from a loaded
  458.  * dynamic library, so that we can use API that may not be
  459.  * available on all OS versions.
  460.  * For debugging purposes, if we cannot find the symbol with the
  461.  * usual dynamic library APIs, we manually walk the symbol table
  462.  * of the loaded library. This allows access to unexported
  463.  * symbols such as private_extern internal debugging functions.
  464.  * If module is NULL or the empty string, search all loaded
  465.  * libraries (could be very expensive and should be avoided).
  466.  *
  467.  * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY
  468.  * BREAK UNEXPECTEDLY IN THE FUTURE !
  469.  *
  470.  * Results:
  471.  * Address of given symbol or NULL if unavailable.
  472.  *
  473.  * Side effects:
  474.  * None.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478. MODULE_SCOPE void *
  479. TkMacOSXGetNamedDebugSymbol(
  480.     const char* module,
  481.     const char* symbol)
  482. {
  483.     void* addr = TkMacOSXGetNamedSymbol(module, symbol);
  484. #ifndef __LP64__
  485.     if (!addr) {
  486. const struct mach_header *mh = NULL;
  487. uint32_t i, n = _dyld_image_count();
  488. size_t module_len = 0;
  489. if (module && *module) {
  490.     module_len = strlen(module);
  491. }
  492. for (i = 0; i < n; i++) {
  493.     if (module && *module) {
  494. /* Find image with given module name */
  495. char *name;
  496. const char *path = _dyld_get_image_name(i);
  497. if (!path) {
  498.     continue;
  499. }
  500. name = strrchr(path, '/') + 1;
  501. if (strncmp(name, module, module_len) != 0) {
  502.     continue;
  503. }
  504.     }
  505.     mh = _dyld_get_image_header(i);
  506.     if (mh) {
  507. struct load_command *lc;
  508. struct symtab_command *st = NULL;
  509. struct segment_command *sg = NULL;
  510. uint32_t j, m, nsect = 0, txtsectx = 0;
  511. lc = (struct load_command*)((const char*) mh +
  512. sizeof(struct mach_header));
  513. m = mh->ncmds;
  514. for (j = 0; j < m; j++) {
  515.     /* Find symbol table and index of __text section */
  516.     if (lc->cmd == LC_SEGMENT) {
  517. /* Find last segment before symbol table */
  518. sg = (struct segment_command*) lc;
  519. if (!txtsectx) {
  520.     /* Count total sections until (__TEXT, __text) */
  521.     uint32_t k, ns = sg->nsects;
  522.     if (strcmp(sg->segname, SEG_TEXT) == 0) {
  523. struct section *s = (struct section *)(
  524. (char *)sg +
  525. sizeof(struct segment_command));
  526. for(k = 0; k < ns; k++) {
  527.     if (strcmp(s->sectname, SECT_TEXT) == 0) {
  528. txtsectx = nsect+k+1;
  529. break;
  530.     }
  531.     s++;
  532. }
  533.     }
  534.     nsect += ns;
  535. }
  536.     } else if (!st && lc->cmd == LC_SYMTAB) {
  537. st = (struct symtab_command*) lc;
  538. break;
  539.     }
  540.     lc = (struct load_command *)((char *) lc + lc->cmdsize);
  541. }
  542. if (st && sg && txtsectx) {
  543.     intptr_t base, slide = _dyld_get_image_vmaddr_slide(i);
  544.     char *strings;
  545.     struct nlist *sym;
  546.     uint32_t strsize = st->strsize;
  547.     int32_t strx;
  548.     /* Offset file positions by difference to actual position
  549.        in memory of last segment before symbol table: */
  550.     base = (intptr_t) sg->vmaddr + slide - sg->fileoff;
  551.     strings = (char*)(base + st->stroff);
  552.     sym = (struct nlist*)(base + st->symoff);
  553.     m = st->nsyms;
  554.     for (j = 0; j < m; j++) {
  555. /* Find symbol with given name in __text section */
  556. strx = sym->n_un.n_strx;
  557. if ((sym->n_type & N_TYPE) == N_SECT &&
  558. sym->n_sect == txtsectx &&
  559. strx > 0 && (uint32_t) strx < strsize &&
  560. strcmp(strings + strx, symbol) == 0) {
  561.     addr = (char*) sym->n_value + slide;
  562.     break;
  563. }
  564. sym++;
  565.     }
  566. }
  567.     }
  568.     if (module && *module) {
  569. /* If given a module name, only search corresponding image */
  570. break;
  571.     }
  572. }
  573.     }
  574. #endif /* __LP64__ */
  575.     return addr;
  576. }