From e8c3c8c58200331ef8a077650bb7238c554cd3da Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Fri, 8 Oct 1999 17:51:45 +0000 Subject: [PATCH] First Checked In. --- .../MetroNubUtils/About MetroNub Utilities | 0 .../MetroNubUtils/MetroNubUserInterface.h | 0 gc/boehm/MetroNubUtils/MetroNubUtils.c | 0 gc/boehm/MetroNubUtils/MetroNubUtils.h | 0 gc/boehm/xSYM/SymFiles.cpp | 302 ++++++++++++++++++ gc/boehm/xSYM/SymFiles.h | 260 +++++++++++++++ gc/boehm/xSYM/sym_file.h | 56 ++++ 7 files changed, 618 insertions(+) create mode 100644 gc/boehm/MetroNubUtils/About MetroNub Utilities create mode 100644 gc/boehm/MetroNubUtils/MetroNubUserInterface.h create mode 100644 gc/boehm/MetroNubUtils/MetroNubUtils.c create mode 100644 gc/boehm/MetroNubUtils/MetroNubUtils.h create mode 100644 gc/boehm/xSYM/SymFiles.cpp create mode 100644 gc/boehm/xSYM/SymFiles.h create mode 100644 gc/boehm/xSYM/sym_file.h diff --git a/gc/boehm/MetroNubUtils/About MetroNub Utilities b/gc/boehm/MetroNubUtils/About MetroNub Utilities new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gc/boehm/MetroNubUtils/MetroNubUserInterface.h b/gc/boehm/MetroNubUtils/MetroNubUserInterface.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gc/boehm/MetroNubUtils/MetroNubUtils.c b/gc/boehm/MetroNubUtils/MetroNubUtils.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gc/boehm/MetroNubUtils/MetroNubUtils.h b/gc/boehm/MetroNubUtils/MetroNubUtils.h new file mode 100644 index 00000000000..e69de29bb2d diff --git a/gc/boehm/xSYM/SymFiles.cpp b/gc/boehm/xSYM/SymFiles.cpp new file mode 100644 index 00000000000..3da02c0f5d0 --- /dev/null +++ b/gc/boehm/xSYM/SymFiles.cpp @@ -0,0 +1,302 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Patrick C. Beard + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License (the "GPL"), in which case the + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#include +#include +#include +#include + +#include "SymFiles.h" +#include "sym_file.h" +#include "gc.h" + +extern "C" { +FILE* FSp_fopen(ConstFSSpecPtr spec, const char * open_mode); +} + +static int getFileReferenceTableEntry(FILE* symFile, + const DiskSymbolHeaderBlock& header, + const FileReference& fileRef, + FileReferenceTableEntry* frte) +{ + UInt32 fileRefsPerPage = (header.dshb_page_size / sizeof(FileReferenceTableEntry)); + UInt32 fileRefPage = (fileRef.fref_frte_index / fileRefsPerPage); + UInt32 fileRefIndex = (fileRef.fref_frte_index % fileRefsPerPage); + + // seek to the specified frte. + fseek(symFile, (header.dshb_frte.dti_first_page + fileRefPage) * header.dshb_page_size + fileRefIndex * sizeof(FileReferenceTableEntry), SEEK_SET); + return fread(frte, sizeof(FileReferenceTableEntry), 1, symFile); +} + +static int getContainedStatementTableEntry(FILE* symFile, + const DiskSymbolHeaderBlock& header, + UInt32 statementIndex, + ContainedStatementsTableEntry* statementEntry) +{ + UInt32 entriesPerPage = (header.dshb_page_size / sizeof(ContainedStatementsTableEntry)); + UInt32 entryPage = (statementIndex / entriesPerPage); + UInt32 entryIndex = (statementIndex % entriesPerPage); + fseek(symFile, (header.dshb_csnte.dti_first_page + entryPage) * header.dshb_page_size + entryIndex * sizeof(ContainedStatementsTableEntry), SEEK_SET); + return fread(statementEntry, sizeof(ContainedStatementsTableEntry), 1, symFile); +} + +inline UInt32 delta(UInt32 x, UInt32 y) +{ + if (x > y) + return (x - y); + else + return (y - x); +} + +inline bool isMeatyModule(const ModulesTableEntry& moduleEntry) +{ + return (moduleEntry.mte_kind == MODULE_KIND_PROCEDURE) || (moduleEntry.mte_kind == MODULE_KIND_FUNCTION); +} + +static const UInt8* getName(const DiskSymbolHeaderBlock& header, const UInt8* nameTable[], UInt32 nameIndex) +{ + UInt32 nameOffset = 2 * nameIndex; + const UInt8* page = nameTable[nameOffset / header.dshb_page_size]; + const UInt8* name = page + (nameOffset % header.dshb_page_size); + return name; +} + +static int getSource(UInt32 codeOffset, FILE* symFile, + const DiskSymbolHeaderBlock& header, + const ResourceTableEntry& codeEntry, + const UInt8* nameTable[], char fileName[256], UInt32* fileOffset) +{ + // since module entries can't span pages, must compute which page module entry size. + UInt32 modulesPerPage = (header.dshb_page_size / sizeof(ModulesTableEntry)); + + // search for MTE nearest specified offset. + // seek to first MTE. + for (UInt16 i = codeEntry.rte_mte_first; i <= codeEntry.rte_mte_last; i++) { + ModulesTableEntry moduleEntry; + UInt32 modulePage = (i / modulesPerPage); + UInt32 moduleIndex = (i % modulesPerPage); + fseek(symFile, (header.dshb_mte.dti_first_page + modulePage) * header.dshb_page_size + moduleIndex * sizeof(ModulesTableEntry), SEEK_SET); + if (fread(&moduleEntry, sizeof(moduleEntry), 1, symFile) == 1) { + const UInt8* moduleName = getName(header, nameTable, moduleEntry.mte_nte_index); + // printf("module name = %#s\n", moduleName); + if (isMeatyModule(moduleEntry) && (codeOffset >= moduleEntry.mte_res_offset) && (codeOffset - moduleEntry.mte_res_offset) < moduleEntry.mte_size) { + FileReferenceTableEntry frte; + if (getFileReferenceTableEntry(symFile, header, moduleEntry.mte_imp_fref, &frte) == 1) { + // get the name of the file. + const UInt8* name = getName(header, nameTable, frte.frte_fn.nte_index); + UInt32 length = name[0]; + BlockMoveData(name + 1, fileName, length); + fileName[length] = '\0'; + // printf("file name = %s\n", fileName); + // try to refine the location, using the contained statements table entries. + UInt32 closestFileOffset = moduleEntry.mte_imp_fref.fref_offset; + UInt32 closestCodeOffset = moduleEntry.mte_res_offset; + UInt32 closestCodeDelta = 0xFFFFFFFF; + UInt32 currentFileOffset, currentCodeOffset = moduleEntry.mte_res_offset, currentCodeDelta; + for (UInt32 j = moduleEntry.mte_csnte_idx_1; j <= moduleEntry.mte_csnte_idx_2; j++) { + ContainedStatementsTableEntry statementEntry; + if (getContainedStatementTableEntry(symFile, header, j, &statementEntry) == 1) { + switch (statementEntry.csnte_file.change) { + case kSourceFileChange: + currentFileOffset = statementEntry.csnte_file.fref.fref_offset; + break; + case kEndOfList: + break; + default: + currentFileOffset += statementEntry.csnte.file_delta; + currentCodeOffset = moduleEntry.mte_res_offset + statementEntry.csnte.mte_offset; + currentCodeDelta = delta(currentCodeOffset, codeOffset); + if (currentCodeDelta < closestCodeDelta) { + closestFileOffset = currentFileOffset; + closestCodeOffset = currentCodeOffset; + closestCodeDelta = currentCodeDelta; + } + break; + } + } + } + *fileOffset = closestFileOffset; + // printf("closest file offset = %d\n", closestFileOffset); + // printf("closest code offset = %d\n", closestCodeOffset); + return 1; + } + } + } + } + return 0; +} + +/** + * Returns the complete name table from the symbol file. + */ +static UInt8** getNameTable(FILE* symFile, const DiskSymbolHeaderBlock& header) +{ + UInt8** nameTable = new UInt8*[header.dshb_nte.dti_page_count]; + long count = 0; + if (nameTable != NULL) { + // seek to first page of the name table. + fseek(symFile, header.dshb_nte.dti_first_page * header.dshb_page_size, SEEK_SET); + // read all of the pages into memory, for speed. + for (int i = 0; i < header.dshb_nte.dti_page_count; i++) { + // allocate each page atomically, so GC won't have to scan them. + UInt8* page = nameTable[i] = (UInt8*) GC_malloc_atomic(header.dshb_page_size); + if (page != NULL) + fread(page, header.dshb_page_size, 1, symFile); + } + } + return nameTable; +} + +struct sym_file { + FILE* mFile; + DiskSymbolHeaderBlock mHeader; + ResourceTableEntry mCodeEntry; + UInt8** mNameTable; + + sym_file() : mFile(NULL), mNameTable(NULL) {} + ~sym_file(); +}; + +sym_file::~sym_file() +{ + // this seems to die when we are being debugged. + if (mFile != NULL) { + ::fclose(mFile); + mFile = NULL; + } + + if (mNameTable != NULL) { + UInt8** nameTable = mNameTable; + UInt16 pageCount = mHeader.dshb_nte.dti_page_count; + while (pageCount-- > 0) { + GC_free(*nameTable++); + } + delete[] mNameTable; + mNameTable = NULL; + } +} + +sym_file* open_sym_file(const FSSpec* symSpec) +{ + sym_file* symbols = new sym_file; + if (symbols != NULL) { + symbols->mFile = FSp_fopen(symSpec, "rb"); + if (symbols->mFile == NULL) + goto err_exit; + + // read the header. should make sure it is a valid .xSYM file, etc. + DiskSymbolHeaderBlock& header = symbols->mHeader; + if (fread(&header, sizeof(header), 1, symbols->mFile) != 1) + goto err_exit; + + // read the RTE tables. + fseek(symbols->mFile, header.dshb_rte.dti_first_page * header.dshb_page_size + sizeof(ResourceTableEntry), SEEK_SET); + for (int i = 1; i <= header.dshb_rte.dti_object_count; i++) { + ResourceTableEntry resEntry; + if (fread(&resEntry, sizeof(resEntry), 1, symbols->mFile) == 1) { + switch (resEntry.rte_ResType) { + case 'CODE': + symbols->mCodeEntry = resEntry; + break; + case 'DATA': + break; + } + } + } + + symbols->mNameTable = getNameTable(symbols->mFile, symbols->mHeader); + } + return symbols; + +err_exit: + delete symbols; + return NULL; +} + +void close_sym_file(sym_file* symbols) +{ + delete symbols; +} + +int get_source(sym_file* symbols, UInt32 codeOffset, char fileName[256], UInt32* fileOffset) +{ + return getSource(codeOffset, symbols->mFile, symbols->mHeader, symbols->mCodeEntry, symbols->mNameTable, fileName, fileOffset); +} + +#if 0 + +int main() +{ + printf ("Opening my own .xSYM file.\n"); + + FILE* symFile = fopen("SymFiles.xSYM", "rb"); + if (symFile != NULL) { + DiskSymbolHeaderBlock header; + if (fread (&header, sizeof(header), 1, symFile) == 1) { + // read the RTE tables. + ResourceTableEntry codeEntry, dataEntry; + fseek(symFile, header.dshb_rte.dti_first_page * header.dshb_page_size + sizeof(ResourceTableEntry), SEEK_SET); + for (int i = 1; i <= header.dshb_rte.dti_object_count; i++) { + ResourceTableEntry resEntry; + if (fread(&resEntry, sizeof(resEntry), 1, symFile) == 1) { + switch (resEntry.rte_ResType) { + case 'CODE': + codeEntry = resEntry; + break; + case 'DATA': + dataEntry = resEntry; + break; + } + } + } + printf("data entry size = %d\n", dataEntry.rte_res_size); + printf("code entry size = %d\n", codeEntry.rte_res_size); + printf("actual code size = %d\n", __code_end__ - __code_start__); + // load the name table. + UInt8** nameTable = getNameTable(symFile, header); + // get source location of a routine. + char fileName[256]; + UInt32 fileOffset; + TV* tv = (TV*)&getSource; + getSource(UInt32(tv->addr - __code_start__) + 536, symFile, header, codeEntry, nameTable, fileName, &fileOffset); + } + fclose(symFile); + } + + return 0; +} + +#endif diff --git a/gc/boehm/xSYM/SymFiles.h b/gc/boehm/xSYM/SymFiles.h new file mode 100644 index 00000000000..2993acfeae7 --- /dev/null +++ b/gc/boehm/xSYM/SymFiles.h @@ -0,0 +1,260 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Patrick C. Beard + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License (the "GPL"), in which case the + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#include + +#ifndef __SYM_FILES__ +#define __SYM_FILES__ + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=mac68k +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(push, 2) +#elif PRAGMA_STRUCT_PACK + #pragma pack(2) +#endif + +/* Note: these structures are for .xSYM file format v3.3. */ + +struct DiskTableInfo { + UInt16 dti_first_page; /* table's first page */ + UInt16 dti_page_count; /* # pages in the table */ + UInt32 dti_object_count; /* # objects in the table */ +}; +typedef struct DiskTableInfo DiskTableInfo; + +struct DiskSymbolHeaderBlock { + Str31 dshb_id; /* Version information */ + UInt16 dshb_page_size; /* Size of the pages/blocks */ + UInt16 dshb_hash_page; /* Disk page for the hash table */ + UInt16 dshb_root_mte; /* MTE index of the program root */ + UInt32 dshb_mod_date; /* executable's mod date */ + + DiskTableInfo dshb_frte; /* Per TABLE information */ + DiskTableInfo dshb_rte; + DiskTableInfo dshb_mte; + DiskTableInfo dshb_cmte; + DiskTableInfo dshb_cvte; + DiskTableInfo dshb_csnte; + DiskTableInfo dshb_clte; + DiskTableInfo dshb_ctte; + DiskTableInfo dshb_tte; + DiskTableInfo dshb_nte; + DiskTableInfo dshb_tinfo; + DiskTableInfo dshb_fite; + DiskTableInfo dshb_const; + + OSType dshb_file_creator; /* executable's creator */ + OSType dshb_file_type; /* executable's file type */ +}; +typedef struct DiskSymbolHeaderBlock DiskSymbolHeaderBlock; + +/* +RESOURCE_TABLE_ENTRY = RECORD + rte_ResType: ResType; { resource type } + rte_res_number: INTEGER; { resource id } + rte_nte_index: LONGINT; { the resource's name } + rte_mte_first: INTEGER; { first MTE contained in the resource } + rte_mte_last: INTEGER; { last MTE contained in the resource } + rte_res_size: LONGINT; { the size of the resource } +END; + */ + +struct ResourceTableEntry { + ResType rte_ResType; /* resource type */ + SInt16 rte_res_number; /* resource id */ + UInt32 rte_nte_index; /* resource name */ + UInt16 rte_mte_first; /* first MTE contained in the resource */ + UInt16 rte_mte_last; /* last MTE contained in the resource */ + UInt32 rte_res_size; /* the size of the resource */ +}; +typedef struct ResourceTableEntry ResourceTableEntry; + +/* +FILE_REFERENCE = RECORD + fref_frte_index: LONGINT; { File Reference Table index } + fref_offset: LONGINT; { absolute offset into the source file } +END; +*/ + +struct FileReference { + UInt16 fref_frte_index; /* File Reference Table index */ + UInt32 fref_offset; /* absolute offset into the source file */ +}; +typedef struct FileReference FileReference; + +/* +MODULES_TABLE_ENTRY = RECORD + mte_rte_index: UNSIGNED; { which resource the MTE is in } + mte_res_offset: LONGINT; { offset into the resource } + mte_size: LONGINT; { size of the MTE } + mte_kind: SignedByte; { kind of MTE } + mte_scope: SignedByte; { MTE's visibility } + mte_parent: INTEGER; { index of parent MTE } + mte_imp_fref: FILE_REFERENCE; { implementation source location } + mte_imp_end: LONGINT; { end of implementation } + mte_nte_index: LONGINT; { MTE's name } + mte_cmte_index: INTEGER; { MTEs contained by this MTE } + mte_cvte_index: LONGINT; { variables contained by this MTE} + mte_clte_index: INTEGER; { labels contained by this MTE } + mte_ctte_index: INTEGER; { types contained by this MTE } + mte_csnte_idx_1: LONGINT; { CSNTE index of first statement } + mte_csnte_idx_2: LONGINT; { CSNTE index of last statement } +END; + */ + +struct ModulesTableEntry { + UInt16 mte_rte_index; /* which resource the MTE is in */ + UInt32 mte_res_offset; /* offset into the resource */ + UInt32 mte_size; /* size of the MTE */ + SInt8 mte_kind; /* kind of MTE */ + SInt8 mte_scope; /* MTE's visibility */ + UInt16 mte_parent; /* index of parent MTE */ + FileReference mte_imp_fref; /* implementation source location */ + UInt32 mte_imp_end; /* end of implementation */ + UInt32 mte_nte_index; /* MTE's name */ + UInt16 mte_cmte_index; /* MTEs contained by this MTE */ + UInt32 mte_cvte_index; /* variables contained by this MTE */ + UInt16 mte_clte_index; /* labels contained by this MTE */ + UInt16 mte_ctte_index; /* types contained by this MTE */ + UInt32 mte_csnte_idx_1; /* CSNTE index of first statement */ + UInt32 mte_csnte_idx_2; /* CSNTE index of last statement */ +}; +typedef struct ModulesTableEntry ModulesTableEntry; + +/* MODULE_KIND_xxx +** The type of module. Taken from the OMF document +*/ +#define MODULE_KIND_NONE 0 +#define MODULE_KIND_PROGRAM 1 +#define MODULE_KIND_UNIT 2 +#define MODULE_KIND_PROCEDURE 3 +#define MODULE_KIND_FUNCTION 4 +#define MODULE_KIND_DATA 5 +#define MODULE_KIND_BLOCK 6 /* The module is an internal block */ + +/* +FILE_REFERENCE_TABLE_ENTRY = RECORD + CASE INTEGER OF + FILE_NAME_INDEX: + ( + frte_name_entry: INTEGER; { = FILE_NAME_INDEX } + frte_nte_index: LONGINT; { name of the source file } + frte_mod_date: LONGINT; { the source file's mod date } + ); + 0: {¥ FILE_NAME_INDEX and ¥ END_OF_LIST, a FRTE entry: } + ( + frte_mte_index: INTEGER; { the MTE's index } + frte_file_offset: LONGINT; { the MTE's source file offset} + ); + END_OF_LIST: + ( + frte_end_of_list: INTEGER; { = END_OF_LIST } + ); +END; +*/ + +enum { + kEndOfList = 0xFFFF, + kFileNameIndex = kEndOfList - 1 +}; + +union FileReferenceTableEntry { + struct { + UInt16 name_entry; /* = kFileNameIndex */ + UInt32 nte_index; /* Name table entry */ + UInt32 mod_date; /* When file was last modified */ + } frte_fn; + + struct { + UInt16 mte_index; /* Module table entry < kFileNameIndex */ + UInt32 file_offset; /* Absolute offset into the source file */ + } frte_mte; + + UInt16 frte_end_of_list; /* = kEndOfList */ +}; +typedef union FileReferenceTableEntry FileReferenceTableEntry; + +/* +CONTAINED_STATEMENTS_TABLE_ENTRY = RECORD + CASE INTEGER OF + SOURCE_FILE_CHANGE: + ( + csnte_file_change: INTEGER; { = SOURCE_FILE_CHANGE } + csnte_fref: FILE_REFERENCE; { the new source file } + ); + 0: {¥ to SOURCE_FILE_CHANGE or END_OF_LIST, a statement entry:} + ( + csnte_mte_index: INTEGER; { the MTE the statement is in } + csnte_file_delta: INTEGER; { delta from previous src loc } + csnte_mte_offset: LONGINT; { code location, offset into MTE } + ); + END_OF_LIST: + ( + csnte_end_of_list: INTEGER; { indicates end of stmt list } + ); +END; + */ + +enum { + kSourceFileChange = kEndOfList - 1 +}; + +union ContainedStatementsTableEntry { + struct { + UInt16 change; /* = kSourceFileChange */ + FileReference fref; /* the new source file */ + } csnte_file; + + struct { + UInt16 mte_index; /* the MTE the statement is in */ + UInt16 file_delta; /* delta from previous src loc */ + UInt32 mte_offset; /* code location, offset into MTE */ + } csnte; + + UInt16 csnte_end_of_list; /* = END_OF_LIST */ +}; +typedef union ContainedStatementsTableEntry ContainedStatementsTableEntry; + +#if PRAGMA_STRUCT_ALIGN + #pragma options align=reset +#elif PRAGMA_STRUCT_PACKPUSH + #pragma pack(pop) +#elif PRAGMA_STRUCT_PACK + #pragma pack() +#endif + +#endif /* __SYM_FILES__ */ diff --git a/gc/boehm/xSYM/sym_file.h b/gc/boehm/xSYM/sym_file.h new file mode 100644 index 00000000000..034d28a16d0 --- /dev/null +++ b/gc/boehm/xSYM/sym_file.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape 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/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is Mozilla Communicator client code, released + * March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * + * Patrick C. Beard + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU Public License (the "GPL"), in which case the + * provisions of the GPL are applicable instead of those above. + * If you wish to allow use of your version of this file only + * under the terms of the GPL and not to allow others to use your + * version of this file under the NPL, indicate your decision by + * deleting the provisions above and replace them with the notice + * and other provisions required by the GPL. If you do not delete + * the provisions above, a recipient may use your version of this + * file under either the NPL or the GPL. + */ + +#pragma once + +#ifndef __FILES__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct sym_file sym_file; + +sym_file* open_sym_file(const FSSpec* symSpec); +void close_sym_file(sym_file* symbols); + +int get_source(sym_file* symbols, UInt32 codeOffset, char fileName[256], UInt32* fileOffset); + +#ifdef __cplusplus +} /* extern "C" */ +#endif