1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #ifndef SYZYGY_REFINERY_TYPES_TYPE_H_
16 : #define SYZYGY_REFINERY_TYPES_TYPE_H_
17 :
18 : #include <stdint.h>
19 : #include <functional>
20 : #include <vector>
21 :
22 : #include "base/logging.h"
23 : #include "base/macros.h"
24 : #include "base/memory/ref_counted.h"
25 : #include "base/strings/string16.h"
26 :
27 : namespace refinery {
28 :
29 : // fwd.
30 : class TypeRepository;
31 : typedef size_t TypeId;
32 :
33 : // A sentinel value for uninitialized types.
34 : const TypeId kNoTypeId = static_cast<TypeId>(-1);
35 :
36 : // A base class for all Type subclasses. Types are owned by a type repository,
37 : // which can vend out type instances by ID on demand.
38 : class Type : public base::RefCounted<Type> {
39 : public:
40 : typedef uint8_t Flags;
41 :
42 : // The set of type classes is closed, each type is enumerated here.
43 : enum TypeKind {
44 : BASIC_TYPE_KIND,
45 : USER_DEFINED_TYPE_KIND,
46 : POINTER_TYPE_KIND,
47 : ARRAY_TYPE_KIND,
48 : FUNCTION_TYPE_KIND,
49 : GLOBAL_TYPE_KIND,
50 : WILDCARD_TYPE_KIND,
51 : };
52 :
53 : enum CV_FLAGS {
54 : FLAG_CONST = 0x0001,
55 : FLAG_VOLATILE = 0x0002,
56 : };
57 :
58 : // @name Accessors
59 : // @{
60 E : TypeRepository* repository() const { return repository_; }
61 E : TypeId type_id() const { return type_id_; }
62 E : const base::string16& name() const { return name_; }
63 E : const base::string16& decorated_name() const { return decorated_name_; }
64 E : size_t size() const { return size_; }
65 E : TypeKind kind() const { return kind_; }
66 : // @}
67 :
68 : // Safely down-cast this to @p SubType.
69 : // @param out the subtype to cast this to.
70 : // @returns true on success, false on failure.
71 : template <class SubType>
72 : bool CastTo(scoped_refptr<SubType>* out);
73 :
74 : // Set the name of the type.
75 : void SetName(const base::string16& name);
76 :
77 : // Set the decorated name of the type.
78 : void SetDecoratedName(const base::string16& decorated_name);
79 :
80 : protected:
81 : friend class base::RefCounted<Type>;
82 :
83 : // This constructor will eventually be removed.
84 : Type(TypeKind kind, const base::string16& name, size_t size);
85 : // This is the way to go.
86 : Type(TypeKind kind,
87 : const base::string16& name,
88 : const base::string16& decorated_name,
89 : size_t size);
90 : virtual ~Type() = 0;
91 :
92 : private:
93 : friend class TypeRepository;
94 : void SetRepository(TypeRepository* repository, TypeId type_id);
95 :
96 : // The type repository this type belongs to and its ID in the repository.
97 : TypeRepository* repository_;
98 : TypeId type_id_;
99 :
100 : // The kind of this type is, synonymous with its class.
101 : const TypeKind kind_;
102 : // Size of type.
103 : const size_t size_;
104 : // Name of type.
105 : base::string16 name_;
106 : // Decorated name of type.
107 : base::string16 decorated_name_;
108 :
109 : DISALLOW_COPY_AND_ASSIGN(Type);
110 : };
111 :
112 : using TypePtr = scoped_refptr<Type>;
113 :
114 : // Constant for no type flags.
115 : const Type::Flags kNoTypeFlags = 0x0000;
116 :
117 : // Represents a basic type, such as e.g. an int, char, void, etc.
118 : class BasicType : public Type {
119 : public:
120 : static const TypeKind ID = BASIC_TYPE_KIND;
121 :
122 : // Creates a new basictype with name @p name and size @p size.
123 : // Sets decorated_name equal to name as basic types have no decorated names.
124 : BasicType(const base::string16& name, size_t size);
125 :
126 : private:
127 : DISALLOW_COPY_AND_ASSIGN(BasicType);
128 : };
129 :
130 : using BasicTypePtr = scoped_refptr<BasicType>;
131 :
132 : // Represents a user defined type such as a struct, union or a class. Also
133 : // represents forward references to such types.
134 : class UserDefinedType : public Type {
135 : public:
136 : class Field;
137 : class Function;
138 : typedef std::vector<Field> Fields;
139 : typedef std::vector<Function> Functions;
140 : static const TypeKind ID = USER_DEFINED_TYPE_KIND;
141 :
142 : enum UdtKind { UDT_CLASS, UDT_STRUCT, UDT_UNION };
143 :
144 : // Creates a new user defined type with name @p name, size @p size.
145 : // This creates an un-finalized UDT with no fields.
146 : // This will eventually be deleted.
147 : UserDefinedType(const base::string16& name, size_t size, UdtKind udt_kind);
148 :
149 : // Creates a new user defined type with name @p name, decorated name @p
150 : // decorated_name and size @p size.
151 : // This creates an un-finalized UDT with no fields.
152 : UserDefinedType(const base::string16& name,
153 : const base::string16& decorated_name,
154 : size_t size,
155 : UdtKind udt_kind);
156 :
157 : // Retrieves the type associated with field @p field_no.
158 : // @pre field_no < fields().size().
159 : // @pre SetRepository has been called.
160 : TypePtr GetFieldType(size_t field_no) const;
161 :
162 : // Retrieves the type associated with function @p function_no.
163 : // @pre function_no < functions().size().
164 : // @pre SetRepository has been called.
165 : TypePtr GetFunctionType(size_t function_no) const;
166 :
167 : // Accessors.
168 : // @{
169 E : const Fields& fields() const { return fields_; }
170 E : const Functions& functions() const { return functions_; }
171 E : bool is_fwd_decl() const { return is_fwd_decl_; }
172 E : UdtKind udt_kind() const { return udt_kind_; }
173 : // @}
174 :
175 : // Finalize the type by providing it with a field list.
176 : // @param fields the fields for the type.
177 : // @param functions the member functions for the type.
178 : // @note this can only be called once per type instance. Moreover this and
179 : // setting the type as a forward declaration are mutually exclusive.
180 : void Finalize(const Fields& fields, const Functions& functions);
181 :
182 : // Set this as forward declaration without concrete class.
183 : // @note this can only be called once per type instance. Moreover this and
184 : // finalizing the UDT are mutually exclusive.
185 : void SetIsForwardDeclaration();
186 :
187 : private:
188 : Fields fields_;
189 : Functions functions_;
190 : bool is_fwd_decl_;
191 : UdtKind udt_kind_;
192 :
193 : DISALLOW_COPY_AND_ASSIGN(UserDefinedType);
194 : };
195 :
196 : using UserDefinedTypePtr = scoped_refptr<UserDefinedType>;
197 :
198 : // Represents a field in a user defined type.
199 : class UserDefinedType::Field {
200 : public:
201 : // TODO(siggi): How to represent VTables/Interfaces?
202 :
203 : // Creates a new field.
204 : // @param name the name of the field.
205 : // @param offset the byte offset of the field within the UDT.
206 : // Note that many bitfield fields can share the same offset within a UDT,
207 : // as can fields in a union.
208 : // @param flags any combination of Flags, denoting properties of the field.
209 : // @param bit_pos if this field is a bitfield, this is the bit position.
210 : // @param bit_len if this field is a bitfield, this is the bit length.
211 : // @param type_id the type ID of the field.
212 : // @note bit_pos and bit_len must be in the range 0..63.
213 : // @note When bit_len is zero it signifies that the field is not a bitfield.
214 : Field(const base::string16& name,
215 : ptrdiff_t offset,
216 : Flags flags,
217 : size_t bit_pos,
218 : size_t bit_len,
219 : TypeId type_id);
220 :
221 : // @name Accessors.
222 : // @{
223 E : const base::string16& name() const { return name_; }
224 E : ptrdiff_t offset() const { return offset_; }
225 E : TypeId type_id() const { return type_id_; }
226 E : size_t bit_pos() const { return bit_pos_; }
227 E : size_t bit_len() const { return bit_len_; }
228 E : bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
229 E : bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
230 : // @}
231 :
232 : bool operator==(const Field& o) const;
233 :
234 : private:
235 : const base::string16 name_;
236 : const ptrdiff_t offset_;
237 : const Flags flags_;
238 : const size_t bit_pos_ : 6;
239 : const size_t bit_len_ : 6;
240 : const TypeId type_id_;
241 : };
242 :
243 : // Represents a member function in UDT.
244 : class UserDefinedType::Function {
245 : public:
246 : // Creates a new member function.
247 : // @param name the name of the field.
248 : // @param type_id the type ID of the function type.
249 : Function(const base::string16& name, TypeId type_id);
250 :
251 : // @name Accessors.
252 : // @{
253 E : const base::string16& name() const { return name_; }
254 E : TypeId type_id() const { return type_id_; }
255 : // @}
256 :
257 : bool operator==(const Function& other) const;
258 :
259 : private:
260 : const base::string16 name_;
261 : const TypeId type_id_;
262 : };
263 :
264 : // Represents a pointer to some other type.
265 : class PointerType : public Type {
266 : public:
267 : static const TypeKind ID = POINTER_TYPE_KIND;
268 :
269 : // Enum describing two pointer modes - regular pointer or reference.
270 : enum Mode {
271 : PTR_MODE_PTR = 0x00,
272 : PTR_MODE_REF = 0x01,
273 : };
274 :
275 : // Creates a new (non-finalized) pointer type with size @p size and value @p
276 : // ptr_mode which determines whether this is actually pointer or reference.
277 : explicit PointerType(size_t size, Mode ptr_mode);
278 :
279 : // Accessors.
280 : // @{
281 E : TypeId content_type_id() const { return content_type_id_; }
282 E : bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
283 E : bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
284 E : Mode ptr_mode() const { return ptr_mode_; }
285 : // @}
286 :
287 : // Retrieves the type this pointer refers to.
288 : // @pre SetRepository has been called.
289 : TypePtr GetContentType() const;
290 :
291 : // Finalize the pointer type with @p flags and @p content_type_id.
292 : void Finalize(Flags flags, TypeId content_type_id);
293 :
294 : private:
295 : // Stores the CV qualifiers of the pointee.
296 : Flags flags_;
297 : // Stores the type this pointer points to.
298 : TypeId content_type_id_;
299 :
300 : // Determines whether this is a reference or an actual pointer.
301 : Mode ptr_mode_;
302 : };
303 :
304 : using PointerTypePtr = scoped_refptr<PointerType>;
305 :
306 : // Represents an array of some other type.
307 : class ArrayType : public Type {
308 : public:
309 : static const TypeKind ID = ARRAY_TYPE_KIND;
310 :
311 : explicit ArrayType(size_t size);
312 :
313 : // Accessors.
314 : // @{
315 E : TypeId index_type_id() const { return index_type_id_; }
316 E : size_t num_elements() const { return num_elements_; }
317 E : TypeId element_type_id() const { return element_type_id_; }
318 :
319 E : bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
320 E : bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
321 : // @}
322 :
323 : // @name Retrieve the index/element types.
324 : // @pre SetRepository has been called.
325 : // @{
326 : TypePtr GetIndexType() const;
327 : TypePtr GetElementType() const;
328 : // @}
329 :
330 : // Finalize the array type.
331 : void Finalize(Flags flags,
332 : TypeId index_type_id,
333 : size_t num_elements,
334 : TypeId element_type_id);
335 :
336 : private:
337 : // The CV qualifiers for the elements.
338 : Flags flags_;
339 :
340 : // The type ID for the the index type.
341 : TypeId index_type_id_;
342 :
343 : // The number of elements in this array.
344 : size_t num_elements_;
345 :
346 : // The type ID for the element type.
347 : TypeId element_type_id_;
348 : };
349 :
350 : using ArrayTypePtr = scoped_refptr<ArrayType>;
351 :
352 : // Represents a function type.
353 : class FunctionType : public Type {
354 : public:
355 : class ArgumentType {
356 : public:
357 : // Creates a new argument.
358 : // @param flags any combination of Flags, denoting properties of the
359 : // argument.
360 : // @param type_id the type ID of the argument.
361 : ArgumentType(Flags flags, TypeId type_id);
362 :
363 : // Default assignment operator.
364 : ArgumentType& operator=(const ArgumentType&) = default;
365 :
366 : // @name Accessors.
367 : // @{
368 E : TypeId type_id() const { return type_id_; }
369 E : bool is_const() const { return (flags_ & FLAG_CONST) != 0; }
370 E : bool is_volatile() const { return (flags_ & FLAG_VOLATILE) != 0; }
371 : // @}
372 :
373 : bool operator==(const ArgumentType& other) const;
374 :
375 : private:
376 : Flags flags_;
377 : TypeId type_id_;
378 : };
379 :
380 : typedef std::vector<ArgumentType> Arguments;
381 : enum CallConvention;
382 :
383 : static const TypeKind ID = FUNCTION_TYPE_KIND;
384 :
385 : // Creates a new (non-finalized) function type.
386 : // @param call_convention calling convention of this function.
387 : explicit FunctionType(CallConvention call_convention);
388 :
389 : // Retrieves the type associated with argument @p arg_no.
390 : // @pre arg_no < arguments().size().
391 : // @pre SetRepository has been called.
392 : TypePtr GetArgumentType(size_t arg_no) const;
393 :
394 : // Retrieves the type associated with the return value.
395 : // @pre SetRepository has been called.
396 : TypePtr GetReturnType() const;
397 :
398 : // Retrieves the type associated with the containing class.
399 : // @pre containing_class_id_ != kNoTypeId
400 : // @pre SetRepository has been called.
401 : TypePtr GetContainingClassType() const;
402 :
403 : // @name Accessors.
404 : // @{
405 E : const Arguments& argument_types() const { return arg_types_; }
406 E : const CallConvention call_convention() const { return call_convention_; }
407 E : const TypeId containing_class_id() const { return containing_class_id_; }
408 E : const ArgumentType& return_type() const { return return_type_; }
409 : // @}
410 :
411 : // @returns true if this is a member function.
412 E : bool IsMemberFunction() const { return containing_class_id_ != kNoTypeId; }
413 :
414 : // Finalize the type by providing it with an argument list and return value.
415 : // @param return_value the return value of the type.
416 : // @param args the arguments for the type.
417 : // @param containing_class_id type index of the containing class.
418 : // @note this can only be called once per type instance.
419 : void Finalize(const ArgumentType& return_type,
420 : const Arguments& arg_types,
421 : TypeId containing_class_id);
422 :
423 : private:
424 : // Stores the arguments.
425 : Arguments arg_types_;
426 :
427 : // The return value.
428 : ArgumentType return_type_;
429 :
430 : // The calling convention of this function.
431 : CallConvention call_convention_;
432 :
433 : // The type index of the containing class or KNoTypeId if this is not a
434 : // member function.
435 : TypeId containing_class_id_;
436 :
437 : DISALLOW_COPY_AND_ASSIGN(FunctionType);
438 : };
439 :
440 : using FunctionTypePtr = scoped_refptr<FunctionType>;
441 :
442 : class GlobalType : public Type {
443 : public:
444 : static const TypeKind ID = GLOBAL_TYPE_KIND;
445 :
446 : // TODO(siggi): Does it even make sense to have size here?
447 : GlobalType(const base::string16& name,
448 : uint64_t rva,
449 : TypeId data_type_id,
450 : size_t size);
451 :
452 : // @name Accessors.
453 : // @{
454 E : uint64_t rva() const { return rva_; }
455 E : TypeId data_type_id() const { return data_type_id_; }
456 : // @}
457 :
458 : // @name Retrieve the data type.
459 : // @pre SetRepository has been called.
460 : TypePtr GetDataType() const;
461 :
462 : private:
463 : uint64_t rva_;
464 : TypeId data_type_id_;
465 :
466 : DISALLOW_COPY_AND_ASSIGN(GlobalType);
467 : };
468 :
469 : using GlobalTypePtr = scoped_refptr<GlobalType>;
470 :
471 : // Enum representing different calling conventions, the values are the same as
472 : // the ones used in the PDB stream.
473 : enum FunctionType::CallConvention {
474 : CALL_NEAR_C = 0x00,
475 : CALL_FAR_C = 0x01,
476 : CALL_NEAR_PASCAL = 0x02,
477 : CALL_FAR_PASCAL = 0x03,
478 : CALL_NEAR_FASTCALL = 0x04,
479 : CALL_FAR_FASTCALL = 0x05,
480 : CALL_SKIPPED = 0x06,
481 : CALL_NEAR_STDCALL = 0x07,
482 : CALL_FAR_STDCALL = 0x08,
483 : CALL_NEAR_SYSCALL = 0x09,
484 : CALL_FAR_SYSCALL = 0x0A,
485 : CALL_THIS_CALL = 0x0B,
486 : CALL_MIPS_CALL = 0x0C,
487 : CALL_GENERIC = 0x0D,
488 : CALL_ALPHACALL = 0x0E,
489 : CALL_PPCCALL = 0x0F,
490 : CALL_SHCALL = 0x10,
491 : CALL_ARMCALL = 0x11,
492 : CALL_AM33CALL = 0x12,
493 : CALL_TRICALL = 0x13,
494 : CALL_SH5CALL = 0x14,
495 : CALL_M32RCALL = 0x15,
496 : CALL_CLRCALL = 0x16,
497 : CALL_RESERVED = 0x17 // first unused call enumeration
498 : };
499 :
500 : // Represents an otherwise unsupported type.
501 : // TODO(siggi): This is a stub, which needs to go away ASAP.
502 : class WildcardType : public Type {
503 : public:
504 : static const TypeKind ID = WILDCARD_TYPE_KIND;
505 :
506 : // Creates a new wildcard type with name @p name, size @p size.
507 : WildcardType(const base::string16& name, size_t size);
508 : // Creates a new wildcard type with name @p name, @p decorated_name and
509 : // size @p size.
510 : WildcardType(const base::string16& name,
511 : const base::string16& decorated_name,
512 : size_t size);
513 : };
514 :
515 : using WildcardTypePtr = scoped_refptr<WildcardType>;
516 :
517 : template <class SubType>
518 E : bool Type::CastTo(scoped_refptr<SubType>* out) {
519 E : DCHECK(out);
520 E : if (SubType::ID != kind()) {
521 E : *out = nullptr;
522 E : return false;
523 : }
524 :
525 E : *out = static_cast<SubType*>(this);
526 E : return true;
527 E : }
528 :
529 : } // namespace refinery
530 :
531 : #endif // SYZYGY_REFINERY_TYPES_TYPE_H_
|