drgn/libdrgn/language.c
Omar Sandoval a97f6c4fa2 Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.

Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.

So, let's reimagine types as being owned by a program. This has a few
parts:

1. In libdrgn, simple types are now created by factory functions,
   drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
   and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
   Program class.
5. While we're changing the API, the parameters to pointer_type() and
   array_type() are reordered to be more logical (and to allow
   pointer_type() to take a default size of None for the program's
   default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
   argument only.

A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-08-26 17:41:09 -07:00

90 lines
2.1 KiB
C

// Copyright (c) Facebook, Inc. and its affiliates.
// SPDX-License-Identifier: GPL-3.0+
#include "internal.h"
#include "language.h"
const struct drgn_language drgn_languages[] = {
[DRGN_LANGUAGE_C] = {
.name = "C",
.format_type_name = c_format_type_name,
.format_type = c_format_type,
.format_object = c_format_object,
.find_type = c_find_type,
.bit_offset = c_bit_offset,
.integer_literal = c_integer_literal,
.bool_literal = c_bool_literal,
.float_literal = c_float_literal,
.op_cast = c_op_cast,
.op_bool = c_op_bool,
.op_cmp = c_op_cmp,
.op_add = c_op_add,
.op_sub = c_op_sub,
.op_mul = c_op_mul,
.op_div = c_op_div,
.op_mod = c_op_mod,
.op_lshift = c_op_lshift,
.op_rshift = c_op_rshift,
.op_and = c_op_and,
.op_or = c_op_or,
.op_xor = c_op_xor,
.op_pos = c_op_pos,
.op_neg = c_op_neg,
.op_not = c_op_not,
},
[DRGN_LANGUAGE_CPP] = {
.name = "C++",
.format_type_name = c_format_type_name,
.format_type = c_format_type,
.format_object = c_format_object,
.find_type = c_find_type,
.bit_offset = c_bit_offset,
.integer_literal = c_integer_literal,
.bool_literal = c_bool_literal,
.float_literal = c_float_literal,
.op_cast = c_op_cast,
.op_bool = c_op_bool,
.op_cmp = c_op_cmp,
.op_add = c_op_add,
.op_sub = c_op_sub,
.op_mul = c_op_mul,
.op_div = c_op_div,
.op_mod = c_op_mod,
.op_lshift = c_op_lshift,
.op_rshift = c_op_rshift,
.op_and = c_op_and,
.op_or = c_op_or,
.op_xor = c_op_xor,
.op_pos = c_op_pos,
.op_neg = c_op_neg,
.op_not = c_op_not,
},
};
struct drgn_error *drgn_language_from_die(Dwarf_Die *die,
const struct drgn_language **ret)
{
Dwarf_Die cudie;
if (dwarf_cu_info(die->cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL))
return drgn_error_libdw();
switch (dwarf_srclang(&cudie)) {
case DW_LANG_C:
case DW_LANG_C89:
case DW_LANG_C99:
case DW_LANG_C11:
*ret = &drgn_language_c;
break;
case DW_LANG_C_plus_plus:
case DW_LANG_C_plus_plus_03:
case DW_LANG_C_plus_plus_11:
case DW_LANG_C_plus_plus_14:
*ret = &drgn_language_cpp;
break;
default:
*ret = NULL;
break;
}
return NULL;
}