root/headers/tools/elfsymbolpatcher/ElfSymbolPatcher.h
//------------------------------------------------------------------------------
//      Copyright (c) 2003, Ingo Weinhold
//
//      Permission is hereby granted, free of charge, to any person obtaining a
//      copy of this software and associated documentation files (the "Software"),
//      to deal in the Software without restriction, including without limitation
//      the rights to use, copy, modify, merge, publish, distribute, sublicense,
//      and/or sell copies of the Software, and to permit persons to whom the
//      Software is furnished to do so, subject to the following conditions:
//
//      The above copyright notice and this permission notice shall be included in
//      all copies or substantial portions of the Software.
//
//      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//      FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//      AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//      LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//      FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
//      DEALINGS IN THE SOFTWARE.
//
//      File Name:              ElfSymbolPatcher.h
//      Author:                 Ingo Weinhold (bonefish@users.sf.net)
//      Description:    Interface declaration of classes used for patching ELF
//                                      symbols. Central class is ElfSymbolPatcher. It is a kind of
//                                      roster, managing all necessary infos (loaded images) and
//                                      being able to fill ElfSymbolPatchInfos with life.
//                                      An ElfSymbolPatchInfo represents a symbol and is able to
//                                      patch/restore it. An ElfSymbolPatchGroup bundles several
//                                      ElfSymbolPatchInfos and can update their data, e.g.
//                                      when images are loaded/unloaded. It uses a
//                                      ElfSymbolPatcher internally and provides a more convenient
//                                      API for the user.
//------------------------------------------------------------------------------

#ifndef ELF_SYMBOL_PATCHER_H
#define ELF_SYMBOL_PATCHER_H

#include <List.h>
#include <String.h>


namespace SymbolPatcher {

class ElfImage;
class ElfSymbolPatcher;
class ElfSymbolPatchGroup;

// ElfSymbolPatchInfo
class ElfSymbolPatchInfo {
public:
                                                                ElfSymbolPatchInfo();
                                                                ~ElfSymbolPatchInfo();

                        status_t                        InitCheck() const;

                        const char*                     GetSymbolName() const;
                        void*                           GetOriginalAddress() const;
                        image_id                        GetOriginalAddressImage() const;

                        status_t                        Patch(void* newAddress);
                        status_t                        Restore();

private:
                        class Entry;

private:
                        void                            Unset();
                        status_t                        SetSymbolName(const char* name);
                        void                            SetOriginalAddress(void* address,
                                                                                                   image_id image);
                        status_t                        CreateEntry(image_id image, BList* targets);
                        bool                            DeleteEntry(image_id image);
                        Entry*                          EntryAt(int32 index);
                        Entry*                          EntryFor(image_id image);

private:
                        friend class ElfSymbolPatcher;
                        friend class ElfSymbolPatchGroup;

                        BString                         fSymbolName;
                        void*                           fOriginalAddress;
                        image_id                        fOriginalAddressImage;
                        BList                           fEntries;
};

// ElfSymbolPatcher
class ElfSymbolPatcher {
public:
                        class UpdateAdapter;

public:
                                                                ElfSymbolPatcher();
                                                                ~ElfSymbolPatcher();

                        status_t                        InitCheck() const;
                        status_t                        Update(UpdateAdapter* updateAdapter = NULL);
                        void                            Unload();

                        status_t                        GetSymbolPatchInfo(const char* symbolName,
                                                                                                   ElfSymbolPatchInfo* info);
                        status_t                        UpdateSymbolPatchInfo(ElfSymbolPatchInfo* info,
                                                                                                          ElfImage* image);

private:
                        status_t                        _Init();
                        void                            _Cleanup();

                        ElfImage*                       _ImageAt(int32 index) const;
                        ElfImage*                       _ImageForID(image_id id) const;

private:
                        BList                           fImages;
                        status_t                        fInitStatus;
};

// UpdateAdapter
class ElfSymbolPatcher::UpdateAdapter {
public:
                                                                UpdateAdapter();
        virtual                                         ~UpdateAdapter();

        virtual void                            ImageAdded(ElfImage* image);
        virtual void                            ImageRemoved(ElfImage* image);
};


// ElfSymbolPatchGroup
class ElfSymbolPatchGroup : private ElfSymbolPatcher::UpdateAdapter {
public:
                                                                ElfSymbolPatchGroup(
                                                                        ElfSymbolPatcher* patcher = NULL);
                                                                ~ElfSymbolPatchGroup();

                        ElfSymbolPatcher*       GetPatcher() const      { return fPatcher; }

                        status_t                        AddPatch(const char* symbolName,
                                                                                 void* newAddress,
                                                                                 void** originalAddress);

                        void                            RemoveAllPatches();

                        status_t                        Patch();
                        status_t                        Restore();

                        status_t                        Update();

private:
                        class PatchInfo : public ElfSymbolPatchInfo {
                        public:
                                void*                   fNewAddress;
                        };

private:
        virtual void                            ImageAdded(ElfImage* image);
        virtual void                            ImageRemoved(ElfImage* image);

private:
                        ElfSymbolPatcher*       fPatcher;
                        BList                           fPatchInfos;
                        bool                            fOwnsPatcher;
                        bool                            fPatched;
};

} // namespace SymbolPatcher

using namespace SymbolPatcher;


#endif  // ELF_SYMBOL_PATCHER_H