aboutsummaryrefslogtreecommitdiff
path: root/lib/Bytecode/Reader/ReaderWrappers.cpp
blob: 218c694f2e4790d34365c040a4cc1d1c287f4084 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#include "ReaderInternals.h"
#include "Support/StringExtras.h"
#include "Config/fcntl.h"
#include "Config/unistd.h"
#include "Config/sys/mman.h"

#define CHECK_ALIGN32(begin,end) \
  if (align32(begin,end)) \
    throw std::string("Alignment error: ReaderWrappers.cpp:" + \
                      utostr((unsigned)__LINE__));

namespace {

  /// BytecodeFileReader - parses a bytecode file from a file
  ///
  class BytecodeFileReader : public BytecodeParser {
  private:
    unsigned char *Buffer;
    int Length;

    BytecodeFileReader(const BytecodeFileReader&); // Do not implement
    void operator=(BytecodeFileReader &BFR);       // Do not implement

  public:
    BytecodeFileReader(const std::string &Filename);
    ~BytecodeFileReader();

  };

  /// BytecodeStdinReader - parses a bytecode file from stdin
  /// 
  class BytecodeStdinReader : public BytecodeParser {
  private:
    std::vector<unsigned char> FileData;
    unsigned char *FileBuf;

    BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement
    void operator=(BytecodeStdinReader &BFR);        // Do not implement

  public:
    BytecodeStdinReader();
    ~BytecodeStdinReader();
  };

  /// FDHandle - Simple handle class to make sure a file descriptor gets closed
  /// when the object is destroyed.
  ///
  class FDHandle {
    int FD;
  public:
    FDHandle(int fd) : FD(fd) {}
    operator int() const { return FD; }
    ~FDHandle() {
      if (FD != -1) close(FD);
    }
  };
}

BytecodeFileReader::BytecodeFileReader(const std::string &Filename) {
  FDHandle FD = open(Filename.c_str(), O_RDONLY);
  if (FD == -1)
    throw std::string("Error opening file!");

  // Stat the file to get its length...
  struct stat StatBuf;
  if (fstat(FD, &StatBuf) == -1 || StatBuf.st_size == 0)
    throw std::string("Error stat'ing file!");

  // mmap in the file all at once...
  Length = StatBuf.st_size;
  unsigned char *Buffer = (unsigned char*)mmap(0, Length, PROT_READ, 
                                               MAP_PRIVATE, FD, 0);
  if (Buffer == (unsigned char*)MAP_FAILED)
    throw std::string("Error mmapping file!");

  // Parse the bytecode we mmapped in
  ParseBytecode(Buffer, Length, Filename);
}

BytecodeFileReader::~BytecodeFileReader() {
  // Unmmap the bytecode...
  munmap((char*)Buffer, Length);
}


#define ALIGN_PTRS 0

BytecodeStdinReader::BytecodeStdinReader() {
  int BlockSize;
  unsigned char Buffer[4096*4];

  // Read in all of the data from stdin, we cannot mmap stdin...
  while ((BlockSize = read(0 /*stdin*/, Buffer, 4096*4))) {
    if (BlockSize == -1)
      throw std::string("Error reading from stdin!");

    FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
  }

  if (FileData.empty())
    throw std::string("Standard Input empty!");

#if ALIGN_PTRS
  FileBuf = (unsigned char*)mmap(0, FileData.size(), PROT_READ|PROT_WRITE, 
                                 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
  assert((Buf != (unsigned char*)-1) && "mmap returned error!");
  memcpy(Buf, &FileData[0], FileData.size());
#else
  FileBuf = &FileData[0];
#endif

#if 0
  // Allocate a new buffer to hold the bytecode...
  unsigned char *ParseBegin=0;
  unsigned Offset=0;
  if ((intptr_t)Buffer & 3) {
    delete [] Buffer;
    Buffer = new unsigned char[Length+4];
    Offset = 4-((intptr_t)Buffer & 3);  // Make sure it's aligned
  }
  memcpy(Buffer+Offset, Buf, Length);          // Copy it over
  ParseBegin = Buffer+Offset;
#endif

  ParseBytecode(FileBuf, FileData.size(), "<stdin>");
}

BytecodeStdinReader::~BytecodeStdinReader() {
#if ALIGN_PTRS
  munmap((char*)FileBuf, FileData.size());   // Free mmap'd data area
#endif
}

///
///
AbstractModuleProvider* 
getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length,
                                const std::string &ModuleID) {
  CHECK_ALIGN32(Buffer, Buffer+Length);
  BytecodeParser *Parser = new BytecodeParser();
  Parser->ParseBytecode(Buffer, Length, ModuleID);
  return Parser;
}

Module *ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length,
                            const std::string &ModuleID, std::string *ErrorStr){
  AbstractModuleProvider *AMP = 
    getBytecodeBufferModuleProvider(Buffer, Length, ModuleID);
  Module *M = AMP->releaseModule();
  delete AMP;
  return M;
}


/// Parse and return a class file...
///
AbstractModuleProvider*
getBytecodeModuleProvider(const std::string &Filename) {
  if (Filename != std::string("-"))        // Read from a file...
    return new BytecodeFileReader(Filename);
  else                                     // Read from stdin
    return new BytecodeStdinReader();
}

Module *ParseBytecodeFile(const std::string &Filename, std::string *ErrorStr) {
  AbstractModuleProvider *AMP = getBytecodeModuleProvider(Filename);
  Module *M = AMP->releaseModule();
  delete AMP;
  return M;
}