text: /*
   * See the dyninst/COPYRIGHT file for copyright information.
   * 
   * We provide the Paradyn Tools (below described as "Paradyn")
   * on an AS IS basis, and do not warrant its validity or performance.
   * We reserve the right to update, modify, or discontinue this
   * software at any time.  We shall have no obligation to supply such
   * updates or modifications or any other form of support to you.
   * 
   * By your use of Paradyn, you understand and agree that we (or any
   * other person or entity with proprietary rights in Paradyn) are
   * under no obligation to provide either maintenance services,
   * update services, notices of latent defects, or correction of
   * defects for Paradyn.
   * 
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   * 
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   * 
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #if !defined(_CODE_BUFFER_H_)
  #define _CODE_BUFFER_H_
  
  
  
  // Infrastructure for the code generating Widgets; try to automate
  // as much of the handling as we can.
  //
  // Background
  //  An Widget can generate two types of code: PIC and non-PIC. PIC code can be treated
  //  as a sequence of bytes that can be freely copied around, whereas non-PIC code must
  //  be tweaked whenever its address changes as part of code generation. Note, it is safe
  //  treat PIC code as non-PIC (though less than optimal); the reverse is not true. For
  //  efficiency we want to bundle PIC code together and avoid re-generating it in every pass,
  //  while keeping callbacks for non-PIC code. 
  //
  //  Another requirement of this system is to build a tracking data structure that maps from
  //  address in the generated code to who generated that code, so we can maintain a mapping 
  //  between original addresses and moved (relocated) code. We also wish to do this automatically.
  //
  //  Thus, we provide an interface that automates these two functions as much as possible. We provide
  //  two ways of specifying code: copy and patch. Copy handles PIC code, and pulls in a buffer of bytes
  //  (e.g., memcpy). Patch registers a callback for later that will provide some code. 
  //
  //  With these two methods the user can specify a tracking data structure that specifies what kind
  //  of code they have provided.
  
  #include "common/h/dyntypes.h"
  #include <list>
  #include "dyninstAPI/src/codegen.h"
  
  class codeGen;
  
  namespace Dyninst {
  namespace Relocation {
          
  // The input grammar to the CodeBuffer is [PIC|nonPIC]*. However, it is safe to accumulate
  // between adjacent PICs, so we can simplify this to ((PIC*)nonPIC)*. This drives our internal
  // storage, which is a list of (buffer, patch) pairs; the buffer contains (PIC*) and the
  // patch represents a nonPIC entry. For each pair, we also associate a list of code trackers, 
  // since there is a 1:1 relationship between each element (PIC, nonPIC) and a tracker. 
          
  class TrackerElement;
  struct Patch;
  class CodeTracker;
  class CodeMover;
  
  class CodeBuffer {
    public: 
     typedef std::vector<unsigned char> Buffer;
    private:
     
     struct Label {
        typedef enum {
           Invalid,
           Absolute,
           Relative,
           Estimate } Type;
        typedef unsigned Id;
  
        Type type;
        Id id;
        int iteration;
        // This is a bit of a complication. We want to estimate
        // where a label will go pre-generation to try and
        // reduce how many iterations we need to go through. Thus,
        // addr may either be an absolute address,
        // an offset, or an estimated address.
        Address addr;
  
        static const unsigned INVALID;
  
        Label() 
        : type(Invalid), id(0), iteration(0), addr(0) {};
        Label(Type a, Id b, Address c)
        : type(a), id(b), iteration(0), addr(c) { assert(id != INVALID); };
        ~Label() {};
        bool valid() { return type != Invalid; };
     };
  
     class BufferElement {
        friend class CodeBuffer;
       public:
        BufferElement();
        ~BufferElement();
        void setLabelID(unsigned id);
        void addPIC(const unsigned char *input, unsigned size, TrackerElement *tracker);
        void addPIC(const Buffer &buffer, TrackerElement *tracker);
        void setPatch(Patch *patch, TrackerElement *tracker);
  
        bool full() { return patch_ != NULL; };
        bool empty();
        bool generate(CodeBuffer *buf,
                      codeGen &gen,
                      int &shift,
                      bool &regenerate);
        bool extractTrackers(CodeTracker *t);
  
       private:
        void addTracker(TrackerElement *tracker);
  
        Address addr_;
        unsigned size_;
        Buffer buffer_;
        Patch *patch_;
        unsigned labelID_;
        // Here the Offset is an offset within the buffer, starting at 0.
        typedef std::map<Offset, TrackerElement *> Trackers;
        Trackers trackers_;
     };
     
    public:
     CodeBuffer();
     ~CodeBuffer();
     
     void initialize(const codeGen &templ, unsigned numBlocks);
     
     unsigned getLabel();
     unsigned defineLabel(Address addr);
     void addPIC(const unsigned char *input, unsigned size, TrackerElement *tracker);
     void addPIC(const void *input, unsigned size, TrackerElement *tracker);
     void addPIC(const codeGen &gen, TrackerElement *tracker);
     void addPIC(const Buffer buf, TrackerElement *tracker);
     void addPatch(Patch *patch, TrackerElement *tracker);
     bool extractTrackers(CodeTracker *t);
  
     unsigned size() const;
     void *ptr() const;
  
     bool generate(Address baseAddr);
     void updateLabel(unsigned id, Address addr, bool &regenerate);
     
     Address predictedAddr(unsigned labelID);
     Address getLabelAddr(unsigned labelID);
  
     void disassemble() const;
  
  
     codeGen &gen() { return gen_; };
    private:
  
     BufferElement &current();
  
     typedef std::list<BufferElement> Buffers;
     Buffers buffers_;
  
     unsigned size_;
  
     codeGen gen_;
  
     int curIteration_;
  
     //typedef std::map<int, Label> Labels;
     typedef std::vector<Label> Labels;
  
     Labels labels_;
     int curLabelID_;
  
     int shift_;
  
     bool generated_;
  };
  };
  };
  
  
  #endif
  