summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c')
-rw-r--r--src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c587
1 files changed, 587 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c
new file mode 100644
index 00000000..a5ecce78
--- /dev/null
+++ b/src/libs/xpcom18a4/nsprpub/pr/src/md/mac/macdll.c
@@ -0,0 +1,587 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape Portable Runtime (NSPR).
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <string.h>
+
+#include <Files.h>
+#include <Errors.h>
+#include <Folders.h>
+#include <CodeFragments.h>
+#include <Aliases.h>
+#include <Resources.h>
+
+#include "IterateDirectory.h" /* MoreFiles */
+
+#include "MacErrorHandling.h"
+#include "macdll.h"
+#include "mdmac.h"
+#include "macio.h"
+
+#include "primpl.h"
+#include "plstr.h"
+
+/*
+ turds used to iterate through the directories looking
+ for the desired library.
+*/
+
+struct GetSharedLibraryFilterProcData
+{
+ Boolean inRecursive;
+ StringPtr inName;
+
+ Boolean outFound;
+ CFragConnectionID outID;
+ Ptr outAddress;
+ OSErr outError;
+};
+typedef struct GetSharedLibraryFilterProcData GetSharedLibraryFilterProcData;
+
+static pascal void
+GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData);
+
+
+/*
+ NSGetSharedLibrary
+
+ Unfortunately CFM doesn't support user specified loader paths,
+ so we emulate the behavior. Effectively this is a GetSharedLibrary
+ where the loader path is user defined.
+*/
+
+OSErr
+NSGetSharedLibrary(Str255 inLibName, CFragConnectionID* outID, Ptr* outMainAddr)
+{
+ char* curLibPath;
+ char* freeCurLibPath;
+ OSErr tempErr;
+ Boolean recursive;
+ FSSpec curFolder;
+ GetSharedLibraryFilterProcData filterData;
+ char *endCurLibPath;
+ Boolean done;
+
+ filterData.outFound = false;
+ filterData.outID = (CFragConnectionID)(-1);
+ filterData.outAddress = NULL;
+ filterData.inName = inLibName;
+
+ freeCurLibPath = curLibPath = PR_GetLibraryPath();
+
+ if (curLibPath == NULL)
+ return (cfragNoLibraryErr);
+
+ tempErr = cfragNoLibraryErr;
+
+ do
+ {
+ endCurLibPath = PL_strchr(curLibPath, PR_PATH_SEPARATOR);
+ done = (endCurLibPath == NULL);
+
+#if 0
+ // we overload the first character of a path if it's :
+ // then we want to recursively search that path
+ // see if path should be recursive
+ if (*curLibPath == ':')
+ {
+ // ':' is an illegal character in the name of a file
+ // if we start any path with this, we want to allow
+ // search recursively
+ curLibPath++;
+ recursive = true;
+ }
+ else
+#endif
+ {
+ recursive = false;
+ }
+
+ if (!done)
+ *endCurLibPath = '\0'; // NULL terminate the string
+
+ // convert to FSSpec
+ tempErr = ConvertUnixPathToFSSpec(curLibPath, &curFolder);
+
+ // now look in this directory
+ if (noErr == tempErr)
+ {
+ filterData.inRecursive = recursive;
+ FSpIterateDirectory(&curFolder, recursive ? 0 : 1, &GetSharedLibraryFilterProc, &filterData);
+
+ if (filterData.outFound)
+ {
+ *outID = filterData.outID;
+ *outMainAddr = filterData.outAddress;
+ tempErr = noErr;
+ break;
+ }
+ else
+ {
+ tempErr = cfragNoLibraryErr;
+ }
+ }
+
+ curLibPath = endCurLibPath + 1; // skip to next path (past the '\0');
+ } while (!done);
+
+ free(freeCurLibPath);
+ return (tempErr);
+}
+
+
+static Boolean
+LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength);
+
+
+/*
+ GetSharedLibraryFilterProc
+
+ Callback to FSpIterateDirectory, finds a library with the name matching the
+ data in inFilterData (of type GetSharedLibraryFilterProcData). Forces a quit
+ when a match is found.
+*/
+
+static pascal void
+GetSharedLibraryFilterProc(const CInfoPBRec* const inCpb, Boolean* inWantQuit, void *inFilterData)
+{
+ GetSharedLibraryFilterProcData* pFilterData = (GetSharedLibraryFilterProcData*) inFilterData;
+
+ if ((inCpb->hFileInfo.ioFlAttrib & (1 << ioDirFlg)) == 0)
+ {
+ FSSpec fragSpec;
+ OSErr tempErr;
+ Str255 errName;
+ Boolean crap;
+ UInt32 codeOffset;
+ UInt32 codeLength;
+
+ // it's a file
+
+ // ¥ fix-me do we really want to allow all 'APPL's' for in which to find this library?
+ switch (inCpb->hFileInfo.ioFlFndrInfo.fdType)
+ {
+ case kCFragLibraryFileType:
+ case 'APPL':
+ tempErr = FSMakeFSSpec(inCpb->hFileInfo.ioVRefNum, inCpb->hFileInfo.ioFlParID, inCpb->hFileInfo.ioNamePtr, &fragSpec);
+
+ // this shouldn't fail
+ if (noErr != tempErr)
+ {
+ return;
+ }
+
+ // resolve an alias if this was one
+ tempErr = ResolveAliasFile(&fragSpec, true, &crap, &crap);
+
+ // if got here we have a shlb (or app-like shlb)
+ if (noErr != tempErr)
+ {
+ // probably couldn't resolve an alias
+ return;
+ }
+
+ break;
+ default:
+ return;
+ }
+
+ // see if this symbol is in this fragment
+ if (LibInPefContainer(&fragSpec, pFilterData->inName, &codeOffset, &codeLength))
+ tempErr = GetDiskFragment(&fragSpec, codeOffset, codeLength, fragSpec.name, kLoadCFrag, &pFilterData->outID, &pFilterData->outAddress, errName);
+ else
+ return;
+
+ // stop if we found a library by that name
+ if (noErr == tempErr)
+ {
+ *inWantQuit = true;
+ pFilterData->outFound = true;
+ pFilterData->outError = tempErr;
+ }
+ }
+ // FSpIterateDirectory will automagically call us for subsequent sub-dirs if necessary
+}
+
+
+/*
+ LibInPefContainer
+
+ Tell whether library inName is contained it the file pointed to by inSpec.
+ Return the codeOffset and codeLength information, for a subsequent
+ call to GetDiskFragment.
+*/
+
+static Boolean
+LibInPefContainer(const FSSpec* inSpec, StringPtr inName, UInt32* outCodeOffset, UInt32* outCodeLength)
+{
+ short refNum;
+ CFragResourceHandle hCfrg;
+ CFragResourceMember* pCurItem;
+ UInt32 curLibIndex;
+ Boolean found;
+
+ // asume we didn't find it
+ found = false;
+
+ // open the resource fork, if we can't bail
+ refNum = FSpOpenResFile(inSpec, fsRdPerm);
+ require(-1 != refNum, Exit);
+
+ // grab out the alias record, if it's not there bail
+ hCfrg = (CFragResourceHandle) Get1Resource(kCFragResourceType, kCFragResourceID);
+ require(NULL != hCfrg, CloseResourceAndExit);
+
+ HLock((Handle)hCfrg);
+
+ // get ptr to first item
+ pCurItem = &(*hCfrg)->firstMember;
+ for (curLibIndex = 0; curLibIndex < (*hCfrg)->memberCount; curLibIndex++)
+ {
+ // is this our library?
+ if ((pCurItem->name[0] == inName[0]) &&
+ (strncmp((char*) inName + 1, (char*) pCurItem->name + 1, PR_MIN(pCurItem->name[0], inName[0])) == 0))
+ {
+ *outCodeOffset = pCurItem->offset;
+ *outCodeLength = pCurItem->length;
+ found = true;
+ }
+
+ // skip to next one
+ pCurItem = (CFragResourceMember*) ((char*) pCurItem + pCurItem->memberSize);
+ }
+
+ HUnlock((Handle)hCfrg);
+
+CloseResourceAndExit:
+ CloseResFile(refNum);
+Exit:
+ return (found);
+
+}
+
+
+/*
+ NSFindSymbol
+
+ Workaround bug in CFM FindSymbol (in at least 7.5.5) where symbols with lengths
+ greater than 63 chars cause a "paramErr". We iterate through all symbols
+ in the library to find the desired symbol.
+*/
+
+OSErr
+NSFindSymbol(CFragConnectionID inID, Str255 inSymName, Ptr* outMainAddr, CFragSymbolClass *outSymClass)
+{
+ OSErr err;
+
+ if (inSymName[0] > 63)
+ {
+ /*
+ if there are greater than 63 characters in the
+ name, CFM FindSymbol fails, so let's iterate through all
+ of the symbols in the fragment and grab it
+ that way.
+ */
+ long symbolCount;
+ Str255 curSymName;
+ long curIndex;
+ Boolean found;
+
+ found = false;
+ err = CountSymbols(inID, &symbolCount);
+ if (noErr == err)
+ {
+ /* now iterate through all the symbols in the library */
+ /* per DTS the indices apparently go 0 to n-1 */
+ for (curIndex = 0; (curIndex <= symbolCount - 1 && !found); curIndex++)
+ {
+ err = GetIndSymbol(inID, curIndex, curSymName, outMainAddr, outSymClass);
+ if (noErr == err && curSymName[0] == inSymName[0] && !strncmp((char*)curSymName + 1, (char*)inSymName + 1, curSymName[0]))
+ {
+ /* found our symbol */
+ found = true;
+ }
+ }
+
+ /* if we didn't find it set the error code so below it won't take this symbol */
+ if (!found)
+ err = cfragNoSymbolErr;
+ }
+ }
+ else
+ {
+ err = FindSymbol(inID, inSymName, outMainAddr, outSymClass);
+ }
+
+ return (err);
+}
+
+
+#pragma mark -
+
+
+/*-----------------------------------------------------------------
+
+ GetNamedFragmentOffsets
+
+ Get the offsets into the data fork of the named fragment,
+ by reading the 'cfrg' resoruce.
+
+-----------------------------------------------------------------*/
+OSErr GetNamedFragmentOffsets(const FSSpec *fileSpec, const char* fragmentName,
+ UInt32 *outOffset, UInt32 *outLength)
+{
+ CFragResourceHandle cFragHandle;
+ short fileRefNum;
+ OSErr err = noErr;
+
+ fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
+ err = ResError();
+ if (err != noErr) return err;
+
+ cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
+ if (!cFragHandle)
+ {
+ err = resNotFound;
+ goto done;
+ }
+
+ /* nothing here moves memory, so no need to lock the handle */
+
+ err = cfragNoLibraryErr; /* in case of failure */
+ *outOffset = 0;
+ *outLength = 0;
+
+ /* Now look for the named fragment */
+ if ((**cFragHandle).memberCount > 0)
+ {
+ CFragResourceMemberPtr memberPtr;
+ UInt16 i;
+
+ for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
+ i < (**cFragHandle).memberCount;
+ i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
+ {
+ char memberName[256];
+ UInt16 nameLen = PR_MIN(memberPtr->name[0], 255);
+
+ // avoid malloc here for speed
+ strncpy(memberName, (char *)&memberPtr->name[1], nameLen);
+ memberName[nameLen] = '\0';
+
+ // fragment names are case insensitive, so act like the system
+ if (PL_strcasecmp(memberName, fragmentName) == 0)
+ {
+ *outOffset = memberPtr->offset;
+ *outLength = memberPtr->length;
+ err = noErr;
+ break;
+ }
+ }
+ }
+
+ /* Resource handle will go away when the res fork is closed */
+
+done:
+ CloseResFile(fileRefNum);
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ GetIndexedFragmentOffsets
+
+ Get the offsets into the data fork of the indexed fragment,
+ by reading the 'cfrg' resoruce.
+
+-----------------------------------------------------------------*/
+OSErr GetIndexedFragmentOffsets(const FSSpec *fileSpec, UInt32 fragmentIndex,
+ UInt32 *outOffset, UInt32 *outLength, char **outFragmentName)
+{
+ CFragResourceHandle cFragHandle;
+ short fileRefNum;
+ OSErr err = noErr;
+
+ fileRefNum = FSpOpenResFile(fileSpec, fsRdPerm);
+ err = ResError();
+ if (err != noErr) return err;
+
+ cFragHandle = (CFragResourceHandle)Get1Resource(kCFragResourceType, kCFragResourceID);
+ if (!cFragHandle)
+ {
+ err = resNotFound;
+ goto done;
+ }
+
+ err = cfragNoLibraryErr; /* in case of failure */
+ *outOffset = 0;
+ *outLength = 0;
+ *outFragmentName = NULL;
+
+ /* the CStrFromPStr mallocs, so might move memory */
+ HLock((Handle)cFragHandle);
+
+ /* Now look for the named fragment */
+ if ((**cFragHandle).memberCount > 0)
+ {
+ CFragResourceMemberPtr memberPtr;
+ UInt16 i;
+
+ for ( i = 0, memberPtr = &(**cFragHandle).firstMember;
+ i < (**cFragHandle).memberCount;
+ i ++, memberPtr = (CFragResourceMemberPtr)((char *)memberPtr + memberPtr->memberSize))
+ {
+
+ if (i == fragmentIndex)
+ {
+ char *fragmentStr;
+ CStrFromPStr(memberPtr->name, &fragmentStr);
+ if (!fragmentStr) /* test for allocation failure */
+ {
+ err = memFullErr;
+ break;
+ }
+
+ *outFragmentName = fragmentStr;
+ *outOffset = memberPtr->offset;
+ *outLength = memberPtr->length;
+ err = noErr;
+ break;
+ }
+ }
+ }
+
+ HUnlock((Handle)cFragHandle);
+
+ /* Resource handle will go away when the res fork is closed */
+
+done:
+ CloseResFile(fileRefNum);
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ NSLoadNamedFragment
+
+ Load the named fragment from the specified file. Aliases must
+ have been resolved by this point.
+
+-----------------------------------------------------------------*/
+
+OSErr NSLoadNamedFragment(const FSSpec *fileSpec, const char* fragmentName, CFragConnectionID *outConnectionID)
+{
+ UInt32 fragOffset, fragLength;
+ short fragNameLength;
+ Ptr main;
+ Str255 fragName;
+ Str255 errName;
+ OSErr err;
+
+ err = GetNamedFragmentOffsets(fileSpec, fragmentName, &fragOffset, &fragLength);
+ if (err != noErr) return err;
+
+ // convert fragment name to pascal string
+ fragNameLength = strlen(fragmentName);
+ if (fragNameLength > 255)
+ fragNameLength = 255;
+ BlockMoveData(fragmentName, &fragName[1], fragNameLength);
+ fragName[0] = fragNameLength;
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+
+ return err;
+}
+
+
+/*-----------------------------------------------------------------
+
+ NSLoadIndexedFragment
+
+ Load the indexed fragment from the specified file. Aliases must
+ have been resolved by this point.
+
+ *outFragName is a malloc'd block containing the fragment name,
+ if returning noErr.
+
+-----------------------------------------------------------------*/
+
+OSErr NSLoadIndexedFragment(const FSSpec *fileSpec, PRUint32 fragmentIndex,
+ char** outFragName, CFragConnectionID *outConnectionID)
+{
+ UInt32 fragOffset, fragLength;
+ char *fragNameBlock = NULL;
+ Ptr main;
+ Str255 fragName = "\p";
+ Str255 errName;
+ OSErr err;
+
+ *outFragName = NULL;
+
+ err = GetIndexedFragmentOffsets(fileSpec, fragmentIndex, &fragOffset, &fragLength, &fragNameBlock);
+ if (err != noErr) return err;
+
+ if (fragNameBlock)
+ {
+ UInt32 nameLen = strlen(fragNameBlock);
+ if (nameLen > 63)
+ nameLen = 63;
+ BlockMoveData(fragNameBlock, &fragName[1], nameLen);
+ fragName[0] = nameLen;
+ }
+
+ // Note that we pass the fragment name as the 4th param to GetDiskFragment.
+ // This value affects the ability of debuggers, and the Talkback system,
+ // to match code fragments with symbol files
+ err = GetDiskFragment(fileSpec, fragOffset, fragLength, fragName,
+ kLoadCFrag, outConnectionID, &main, errName);
+ if (err != noErr)
+ {
+ free(fragNameBlock);
+ return err;
+ }
+
+ *outFragName = fragNameBlock;
+ return noErr;
+}
+
+