retrieve.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 357 行
CPP
357 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include <stdlib.h>
#include "common.hpp"
#include "retrieve.hpp"
unsigned_8 Directory::_orderTable[] = {
1, 2, 6, 6, 4, 0xff, 0xff,
3, 7, 0xff, 0xff, 0xff, 0xff,
5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
// unused function section :
bool cv_dir_entry::operator == ( const cv_dir_entry& ) const {
throw InternalError("cv_dir_entry == gets call.");
}
// unused function section end.
char Retriever::_inputBuffer[DEF_BUF_SIZE];
//
// Directory::Directory().
// Constructs a Directory object that contains the header and entry infos
// by reading from "infile". The file pointer of the directory
// has to be provided.
//
Directory::Directory(ifstream& inFile,
streampos directoryPos)
: _cvDirEntry (0),
_currentSub (0)
/*******************************************/
{
inFile.seekg(directoryPos);
inFile.read( (unsigned char *) &_cvDirHeader,sizeof(cv_subsection_directory));
if ( inFile.ios::fail() ) {
throw DebugInfoError();
}
_cvDirEntry = new cv_dir_entry[_cvDirHeader.cDir];
inFile.read( (unsigned char *) _cvDirEntry,
sizeof(cv_directory_entry)*_cvDirHeader.cDir);
// sort the directory into prefer reading order.
qsort(_cvDirEntry,_cvDirHeader.cDir,sizeof(cv_directory_entry),Directory::Compare);
if ( inFile.ios::fail() ) {
throw DebugInfoError();
}
}
int Directory::CompMod( const module mod1, const module mod2 )
/************************************************************/
{
if ( mod1 < mod2 ) {
return -1;
}
if ( mod1 > mod2 ) {
return 1;
}
return 0;
}
int Directory::CompSub( const unsigned_16 sub1, const unsigned_16 sub2 )
/**********************************************************************/
{
if ( _orderTable[sub1-sstModule] <
_orderTable[sub2-sstModule] ) {
return -1;
}
if ( _orderTable[sub1-sstModule] >
_orderTable[sub2-sstModule] ) {
return 1;
}
return 0;
}
bool Directory::IsModule( const unsigned_16 sub )
/***********************************************/
{
return ( sub == sstTypes ||
sub == sstSymbols ||
sub == sstSrcModule );
}
bool Directory::IsModuleBasis( const unsigned_16 sub1,
const unsigned_16 sub2 )
/*****************************************************/
{
return ( IsModule(sub1) && IsModule(sub2) );
}
int Directory::Compare( const void* ptr1, const void* ptr2 )
/**********************************************************/
{
const cv_dir_entry* cvDirEntry1 = ( cv_dir_entry * ) ptr1;
const cv_dir_entry* cvDirEntry2 = ( cv_dir_entry * ) ptr2;
int retVal;
if ( IsModuleBasis(cvDirEntry1->subsection,cvDirEntry2->subsection) ) {
retVal = CompMod(cvDirEntry1->iMod,cvDirEntry2->iMod);
return retVal ? retVal : CompSub(cvDirEntry1->subsection,cvDirEntry2->subsection);
}
retVal = CompSub(cvDirEntry1->subsection,cvDirEntry2->subsection);
if ( retVal ) {
return retVal;
}
retVal = CompMod(cvDirEntry1->iMod,cvDirEntry2->iMod);
return retVal ? retVal : 0;
}
bool Directory::GetDirInfo( dir_info& di,
const sst subsection,
const module mod )
/**************************************************/
{
if ( _cvDirEntry[_currentSub].subsection == subsection &&
_cvDirEntry[_currentSub].iMod == mod ) {
di.offset = _cvDirEntry[_currentSub].lfo;
di.length = _cvDirEntry[_currentSub].cb;
_currentSub++;
return TRUE;
}
return FALSE;
}
bool Directory::IsAtSubsection( const sst subsection )
/****************************************************/
{
return _cvDirEntry[_currentSub].subsection == subsection;
}
//
// Directory::~Directory().
//
Directory::~Directory()
/*********************/
{
delete [] _cvDirEntry;
}
//
// Retriever::GetBasePos().
// Returns the base address of the debugging informations.
// Assumes OMF style.
//
streampos Retriever::GetBasePos()
/*******************************/
{
unsigned_32 lfoBase;
_inputFile.seekg(-LONG_WORD, ios::end);
_inputFile.read( (char *) &lfoBase,LONG_WORD);
_inputFile.seekg(-lfoBase, ios::end);
if ( _inputFile.ios::fail() ) {
throw DebugInfoError();
}
return (_inputFile.tellg());
}
//
// Retriever::GetDirPos().
// Returns the address of the directory informations.
//
streampos Retriever::GetDirPos()
/******************************/
{
unsigned_32 lfoDir;
if ( ! SeekRead(&lfoDir, _lfaBase + LONG_WORD, LONG_WORD) ) {
throw DebugInfoError();
}
return (_lfaBase+lfoDir);
}
//
// Retriever::SeekRead().
// Seek to a specify point in the file and read some data.
//
unsigned_32 Retriever::SeekRead( void* buffer,
streampos position,
size_t length )
/**************************************************/
{
_inputFile.seekg(position);
if ( _inputFile.ios::fail() ) {
throw DebugInfoError();
}
_inputFile.read( (char *) buffer, length);
if ( _inputFile.ios::rdstate() == ios::badbit ) {
throw DebugInfoError();
}
if ( _inputFile.ios::rdstate() == ios::failbit ) {
if ( _inputFile.gcount() != length ) {
_inputFile.clear();
return _inputFile.gcount();
}
throw DebugInfoError();
}
/* reading past EOF also flags ios::fail() so we need to clear
that state */
_inputFile.ios::clear();
return length;
}
//
// Retriever::Retriever().
// Constructs a Retriever object that is attached to inputStream.
//
Retriever::Retriever( ifstream& inputStream ) :
_inputFile ( inputStream.fstreambase::fd() ),
_lfaBase ( GetBasePos() ),
_aDirectory(_inputFile, GetDirPos()),
_pageStartOffset(0),
_heapBuffer( NULL ),
_missRate(0)
/*************************************************************/
{
ReadPage(0);
CheckSig();
}
//
// Retriever::CheckSig().
// Checks the validness of the CV signature.
//
void Retriever::CheckSig()
/************************/
{
if ( strncmp(_inputBuffer,NB09,4) == 0 ) {
throw MiscError("file already packed.");
}
// NB05 is the only version that we support.
if ( strncmp(_inputBuffer,NB05,4) != 0 ) {
throw CVSigError();
}
}
unsigned_32 Retriever::LocalPageOff( const unsigned_32 offset ) const
/*******************************************************************/
{
return ( offset-_pageStartOffset );
}
bool Retriever::IsCrossPage( const dir_info& di ) const
/*****************************************************/
{
return ( LocalPageOff(di.offset) + di.length > DEF_BUF_SIZE );
}
void Retriever::ReadPage( const unsigned_32 offset )
/**************************************************/
{
if ( ! _inputFile.eof() ) {
SeekRead(_inputBuffer,_lfaBase+offset,DEF_BUF_SIZE);
_pageStartOffset = offset;
}
}
bool Retriever::IsInCurrentPage( const unsigned_32 offset ) const
/***************************************************************/
{
long diff = offset-_pageStartOffset;
return ( diff >= 0 && diff <= DEF_BUF_SIZE );
}
char* Retriever::Read( const dir_info& di )
/*****************************************/
{
// if length larger than one page, then do a direct read and read in
// the subsequent page onto input buffer.
if ( di.length > DEF_BUF_SIZE ) {
_heapBuffer = new char [di.length];
if ( SeekRead(_heapBuffer, _lfaBase+di.offset, di.length) != di.length ) {
delete [] _heapBuffer;
return NULL;
}
ReadPage(di.offset+di.length);
return _heapBuffer;
}
ReadPage(di.offset);
return _inputBuffer;
}
// The read subsection routine is most efficient when debugging info emitted
// by the linker are in the order that cvpack reads.
bool Retriever::ReadSubsection( char*& buffer,
unsigned_32& length,
const sst subsection,
const module mod )
/******************************************************/
{
// release last used heap buffer, if there is one.
// C++ guaranteeds delete NULL without error.
delete [] _heapBuffer;
dir_info di;
if ( !_aDirectory.GetDirInfo(di,subsection,mod) ) {
return FALSE;
}
length = di.length;
if ( length == 0 ) {
return FALSE;
}
if ( _missRate > DEF_MISS_THRESHOLD ) {
_heapBuffer = buffer = new char [di.length];
if ( SeekRead( buffer, _lfaBase+di.offset, di.length ) != di.length ) {
delete [] _heapBuffer;
return FALSE;
}
return TRUE;
}
// if the request read is not in current page, readin the request
// page.
if ( ! IsInCurrentPage(di.offset) ) {
++_missRate;
buffer = Read(di);
return ( buffer ? TRUE : FALSE );
}
if ( IsCrossPage(di) ) {
buffer = Read(di);
return ( buffer ? TRUE : FALSE );
}
buffer = _inputBuffer + LocalPageOff(di.offset);
return TRUE;
}
bool Retriever::IsAtSubsection( const sst subsection )
/****************************************************/
{
return _aDirectory.IsAtSubsection( subsection );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?