root/src/kits/debug/SymbolLookup.h
/*
 * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2013, Rene Gollent, rene@gollent.com.
 * Distributed under the terms of the MIT License.
 */

#ifndef SYMBOL_LOOKUP_H
#define SYMBOL_LOOKUP_H

#include <stdio.h>

#include <image.h>
#include <OS.h>

#include <util/DoublyLinkedList.h>


struct debug_context;
struct image_t;
struct runtime_loader_debug_area;


namespace BPrivate {
namespace Debug {

class Image;


// Exception
class Exception {
public:
        Exception(status_t error)
                : fError(error)
        {
        }

        Exception(const Exception &other)
                : fError(other.fError)
        {
        }

        status_t Error() const  { return fError; }

private:
        status_t        fError;
};


// Area
class Area : public DoublyLinkedListLinkImpl<Area> {
public:
        Area(area_id localID, addr_t remoteAddress, const void* localAddress, int32 size)
                : fLocalID(localID),
                  fRemoteAddress(remoteAddress),
                  fLocalAddress(localAddress),
                  fSize(size)
        {
        }

        ~Area()
        {
                if (fLocalID >= 0)
                        delete_area(fLocalID);
        }

        addr_t          RemoteAddress() const   { return fRemoteAddress; }
        const void* LocalAddress() const        { return fLocalAddress; }
        int32 Size() const                                      { return fSize; }

        bool ContainsAddress(const void *address, int32 size) const
        {
                return (fRemoteAddress <= (addr_t)address
                        && (addr_t)address + size <= (fRemoteAddress + fSize));
        }

        bool ContainsLocalAddress(const void* address) const
        {
                return (addr_t)address >= (addr_t)fLocalAddress
                        && (addr_t)address < (addr_t)fLocalAddress + fSize;
        }

        const void *TranslateAddress(const void *remoteAddress);

private:
        area_id         fLocalID;
        addr_t          fRemoteAddress;
        const void      *fLocalAddress;
        int32           fSize;
};


// RemoteMemoryAccessor
class RemoteMemoryAccessor {
public:
        RemoteMemoryAccessor(debug_context* debugContext);
        ~RemoteMemoryAccessor();

        status_t InitCheck() const;

        const void *PrepareAddress(const void *remoteAddress, int32 size);
        const void *PrepareAddressNoThrow(const void *remoteAddress,
                int32 size);

        template<typename Type> inline const Type &Read(
                const Type &remoteData)
        {
                const void *remoteAddress = &remoteData;
                const void *localAddress = PrepareAddress(remoteAddress,
                        sizeof(remoteData));
                return *(const Type*)localAddress;
        }

        Area* AreaForLocalAddress(const void* address) const;

private:
        Area& _GetArea(const void *address, int32 size);
        status_t _GetAreaNoThrow(const void *address, int32 size, Area *&_area);

        typedef DoublyLinkedList<Area>  AreaList;

protected:
        debug_context* fDebugContext;

private:
        AreaList        fAreas;
};


// SymbolIterator
struct SymbolIterator {
        const Image*            image;
        int32                           currentIndex;
};


// SymbolLookup
class SymbolLookup : private RemoteMemoryAccessor {
public:
        SymbolLookup(debug_context* debugContext, image_id image);
        ~SymbolLookup();

        status_t Init();

        status_t LookupSymbolAddress(addr_t address, addr_t *_baseAddress,
                const char **_symbolName, size_t *_symbolNameLen,
                const char **_imageName, bool *_exactMatch) const;

        status_t InitSymbolIterator(image_id imageID,
                SymbolIterator& iterator) const;
        status_t InitSymbolIteratorByAddress(addr_t address,
                SymbolIterator& iterator) const;
        status_t NextSymbol(SymbolIterator& iterator, const char** _symbolName,
                size_t* _symbolNameLen, addr_t* _symbolAddress, size_t* _symbolSize,
                int32* _symbolType) const;

        status_t GetSymbol(image_id imageID, const char* name, int32 symbolType,
                void** _symbolLocation, size_t* _symbolSize, int32* _symbolType) const;

private:
        class LoadedImage;
        friend class LoadedImage;

private:
        const image_t* _FindLoadedImageAtAddress(addr_t address);
        const image_t* _FindLoadedImageByID(image_id id);
        Image* _FindImageAtAddress(addr_t address) const;
        Image* _FindImageByID(image_id id) const;
        size_t _SymbolNameLen(const char* address) const;
        status_t _LoadImageInfo(const image_info& imageInfo);

private:
        const runtime_loader_debug_area *fDebugArea;
        DoublyLinkedList<Image> fImages;
        image_id fImageID;
};

}       // namespace Debug
}       // namespace BPrivate

using BPrivate::Debug::SymbolLookup;

#endif  // SYMBOL_LOOKUP_H