1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef BCC_RS_INFO_H
18#define BCC_RS_INFO_H
19
20#include <stdint.h>
21
22#include <string>
23#include <utility>
24
25#include "bcc/Support/Log.h"
26#include "bcc/Support/Sha1Util.h"
27
28#include <utils/String8.h>
29#include <utils/Vector.h>
30
31namespace llvm {
32class Module;
33}
34
35namespace bcc {
36
37// Forward declarations
38class FileBase;
39class InputFile;
40class OutputFile;
41class Source;
42class RSScript;
43
44typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
45
46namespace rsinfo {
47
48/* RS info file magic */
49#define RSINFO_MAGIC      "\0rsinfo\n"
50
51/* RS info file version, encoded in 4 bytes of ASCII */
52#define RSINFO_VERSION    "006\0"
53
54struct __attribute__((packed)) ListHeader {
55  // The offset from the beginning of the file of data
56  uint32_t offset;
57  // Number of item in the list
58  uint32_t count;
59  // Size of each item
60  uint8_t itemSize;
61};
62
63typedef uint32_t StringIndexTy;
64
65/* RS info file header */
66struct __attribute__((packed)) Header {
67  // Magic versus version
68  uint8_t magic[8];
69  uint8_t version[4];
70
71  uint8_t isThreadable;
72  uint8_t hasDebugInformation;
73
74  uint16_t headerSize;
75
76  uint32_t strPoolSize;
77
78  // The index in the pool of the SHA-1 checksum of the source file.
79  // It has a fixed-length of SHA1_DIGEST_LENGTH (=20) bytes.
80  StringIndexTy sourceSha1Idx;
81  // The index in the pool of the command used to compile this source.
82  StringIndexTy compileCommandLineIdx;
83  // The index in the pool of the build fingerprint of Android when the source was compiled.
84  StringIndexTy buildFingerprintIdx;
85
86  struct ListHeader pragmaList;
87  struct ListHeader objectSlotList;
88  struct ListHeader exportVarNameList;
89  struct ListHeader exportFuncNameList;
90  struct ListHeader exportForeachFuncList;
91};
92
93// Use value -1 as an invalid string index marker. No need to declare with
94// 'static' modifier since 'const' variable has internal linkage by default.
95const StringIndexTy gInvalidStringIndex = static_cast<StringIndexTy>(-1);
96
97struct __attribute__((packed)) PragmaItem {
98  // Pragma is a key-value pair.
99  StringIndexTy key;
100  StringIndexTy value;
101};
102
103struct __attribute__((packed)) ObjectSlotItem {
104  uint32_t slot;
105};
106
107struct __attribute__((packed)) ExportVarNameItem {
108  StringIndexTy name;
109};
110
111struct __attribute__((packed)) ExportFuncNameItem {
112  StringIndexTy name;
113};
114
115struct __attribute__((packed)) ExportForeachFuncItem {
116  StringIndexTy name;
117  uint32_t signature;
118};
119
120// Return the human-readable name of the given rsinfo::*Item in the template
121// parameter. This is for debugging and error message.
122template<typename Item>
123inline const char *GetItemTypeName();
124
125template<>
126inline const char *GetItemTypeName<PragmaItem>()
127{  return "rs pragma"; }
128
129template<>
130inline const char *GetItemTypeName<ObjectSlotItem>()
131{  return "rs object slot"; }
132
133template<>
134inline const char *GetItemTypeName<ExportVarNameItem>()
135{ return "rs export var"; }
136
137template<>
138inline const char *GetItemTypeName<ExportFuncNameItem>()
139{  return "rs export func"; }
140
141template<>
142inline const char *GetItemTypeName<ExportForeachFuncItem>()
143{ return "rs export foreach"; }
144
145} // end namespace rsinfo
146
147class RSInfo {
148public:
149  typedef const uint8_t* DependencyHashTy;
150  typedef android::Vector<std::pair<const char*, const char*> > PragmaListTy;
151  typedef android::Vector<uint32_t> ObjectSlotListTy;
152  typedef android::Vector<const char *> ExportVarNameListTy;
153  typedef android::Vector<const char *> ExportFuncNameListTy;
154  typedef android::Vector<std::pair<const char *,
155                                    uint32_t> > ExportForeachFuncListTy;
156
157public:
158  // Return the path of the RS info file corresponded to the given output
159  // executable file.
160  static android::String8 GetPath(const char *pFilename);
161
162  // Check whether this info contains the same source hash, compile command line, and fingerprint.
163  // If not, it's an indication we need to recompile.
164  bool IsConsistent(const char* pInputFilename, const DependencyHashTy& sourceHash,
165                    const char* compileCommandLine, const char* buildFingerprint);
166
167private:
168
169  rsinfo::Header mHeader;
170
171  char *mStringPool;
172
173  // Pointer to the hash of the souce file, somewhere in the string pool.
174  DependencyHashTy mSourceHash;
175  // Pointer to the command used to compile this source, somewhere in the string pool.
176  const char* mCompileCommandLine;
177  // Pointer to the build fingerprint of Android when the source was compiled, somewhere in the
178  // string pool.
179  const char* mBuildFingerprint;
180
181  PragmaListTy mPragmas;
182  ObjectSlotListTy mObjectSlots;
183  ExportVarNameListTy mExportVarNames;
184  ExportFuncNameListTy mExportFuncNames;
185  ExportForeachFuncListTy mExportForeachFuncs;
186
187  // Initialize an empty RSInfo with its size of string pool is pStringPoolSize.
188  RSInfo(size_t pStringPoolSize);
189
190  // layout() assigns value of offset in each ListHeader (i.e., it decides where
191  // data should go in the file.) It also updates fields other than offset to
192  // reflect the current RSInfo object states to mHeader.
193  bool layout(off_t initial_offset);
194
195public:
196  ~RSInfo();
197
198  // Implemented in RSInfoExtractor.cpp.
199  static RSInfo *ExtractFromSource(const Source &pSource,
200                                   const DependencyHashTy &sourceHashToEmbed,
201                                   const char* compileCommandLineToEmbed,
202                                   const char* buildFingerprintToEmbed);
203
204  // Implemented in RSInfoReader.cpp.
205  static RSInfo *ReadFromFile(InputFile &pInput);
206
207  // Implemneted in RSInfoWriter.cpp
208  bool write(OutputFile &pOutput);
209
210  void dump() const;
211
212  // const getter
213  inline bool isThreadable() const
214  { return mHeader.isThreadable; }
215  inline bool hasDebugInformation() const
216  { return mHeader.hasDebugInformation; }
217  inline const PragmaListTy &getPragmas() const
218  { return mPragmas; }
219  inline const ObjectSlotListTy &getObjectSlots() const
220  { return mObjectSlots; }
221  inline const ExportVarNameListTy &getExportVarNames() const
222  { return mExportVarNames; }
223  inline const ExportFuncNameListTy &getExportFuncNames() const
224  { return mExportFuncNames; }
225  inline const ExportForeachFuncListTy &getExportForeachFuncs() const
226  { return mExportForeachFuncs; }
227
228  const char *getStringFromPool(rsinfo::StringIndexTy pStrIdx) const;
229  rsinfo::StringIndexTy getStringIdxInPool(const char *pStr) const;
230
231  // setter
232  inline void setThreadable(bool pThreadable = true)
233  { mHeader.isThreadable = pThreadable; }
234
235public:
236  enum FloatPrecision {
237    FP_Full,
238    FP_Relaxed,
239  };
240
241  // Return the minimal floating point precision required for the associated
242  // script.
243  FloatPrecision getFloatPrecisionRequirement() const;
244};
245
246// Returns the arguments concatenated into one string.
247std::string getCommandLine(int argc, const char* const* argv);
248
249} // end namespace bcc
250
251#endif  // BCC_RS_INFO_H
252