aboutsummaryrefslogtreecommitdiff
path: root/libctf
diff options
context:
space:
mode:
Diffstat (limited to 'libctf')
-rw-r--r--libctf/ctf-decl.c20
-rw-r--r--libctf/ctf-dump.c7
-rw-r--r--libctf/ctf-impl.h6
-rw-r--r--libctf/ctf-lookup.c7
-rw-r--r--libctf/ctf-open.c99
-rw-r--r--libctf/ctf-serialize.c5
-rw-r--r--libctf/ctf-types.c2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/array.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/const.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/datasec.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/decl-tag.lk8
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/forward.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/integer.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/pointer.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/restrict.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/struct.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/union.lk2
-rw-r--r--libctf/testsuite/libctf-lookup/by-kind/volatile.lk2
18 files changed, 120 insertions, 54 deletions
diff --git a/libctf/ctf-decl.c b/libctf/ctf-decl.c
index eec6196..4c1007f5 100644
--- a/libctf/ctf-decl.c
+++ b/libctf/ctf-decl.c
@@ -34,7 +34,7 @@
The functions in this file build a set of stacks from the type graph nodes
corresponding to the C operator precedence levels in the appropriate order.
- The code in ctf_type_name() can then iterate over the levels and nodes in
+ The code in ctf_type_aname() can then iterate over the levels and nodes in
lexical precedence order and construct the final C declaration string. */
#include <ctf-impl.h>
@@ -84,11 +84,17 @@ ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
if ((tp = ctf_lookup_by_id (&fp, type, &suffix)) == NULL)
{
- cd->cd_err = fp->ctf_errno;
- return;
+ if (ctf_errno (fp) != ECTF_NONREPRESENTABLE)
+ {
+ cd->cd_err = fp->ctf_errno;
+ return;
+ }
+ kind = CTF_K_UNKNOWN;
}
+ else
+ kind = ctf_type_kind (fp, type);
- switch (kind = ctf_type_kind (fp, type))
+ switch (kind)
{
case CTF_K_ARRAY:
(void) ctf_array_info (fp, type, &ar);
@@ -121,6 +127,12 @@ ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
prec = CTF_PREC_POINTER;
break;
+ case CTF_K_DECL_TAG:
+ case CTF_K_VAR:
+ ctf_decl_push (cd, fp, suffix->ctt_type);
+ prec = CTF_PREC_BASE; /* UPTODO probably wrong */
+ break;
+
case CTF_K_SLICE:
/* Slices themselves have no print representation and should not appear in
the decl stack. */
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
index ad43666..94eac10 100644
--- a/libctf/ctf-dump.c
+++ b/libctf/ctf-dump.c
@@ -614,6 +614,7 @@ ctf_dump_var (ctf_dict_t *fp, ctf_id_t type,
{
char *str;
char *typestr;
+ int linkage;
ctf_dump_state_t *state = arg;
ctf_id_t otype = type;
@@ -625,7 +626,11 @@ ctf_dump_var (ctf_dict_t *fp, ctf_id_t type,
/* Specialized var dumper: only dump the linkage, not the type kind or
anything related. */
- if ((typestr = ctf_type_aname (fp, type)) == NULL)
+ if ((linkage = ctf_type_linkage (fp, type)) < 0
+ || asprintf (&typestr, "%s%s", linkage == 0 ? "static "
+ : (linkage == 2 ? "extern " :
+ (linkage == 1 ? "" : "(invalid linkage) ")),
+ ctf_type_name_raw (fp, type)) < 0)
{
ctf_err_warn (fp, 1, ctf_errno (fp), _("cannot format name dumping var 0x%lx"),
type);
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index 214f265..8f8703c 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -432,12 +432,14 @@ struct ctf_dict
uint32_t *ctf_sxlate; /* Translation table for unindexed symtypetab
entries. */
unsigned long ctf_nsyms; /* Number of entries in symtab xlate table. */
- uint32_t *ctf_txlate; /* Translation table for type IDs. */
+ ctf_type_t **ctf_txlate; /* Translation table for type IDs. */
uint32_t *ctf_ptrtab; /* Translation table for pointer-to lookups. */
size_t ctf_ptrtab_len; /* Num types storable in ptrtab currently. */
uint32_t *ctf_pptrtab; /* Parent types pointed to by child dicts. */
size_t ctf_pptrtab_len; /* Num types storable in pptrtab currently. */
uint32_t ctf_pptrtab_typemax; /* Max child type when pptrtab last updated. */
+ ctf_type_t *ctf_void_type; /* void type, if dynamically constructed. (More
+ space allocated, due to vlen.) */
ctf_dynset_t *ctf_conflicting_enums; /* Tracks enum constants that conflict. */
uint32_t *ctf_funcidx_names; /* Name of each function symbol in symtypetab
(if indexed). */
@@ -619,7 +621,7 @@ extern ctf_id_t ctf_index_to_type (const ctf_dict_t *, uint32_t);
#define LCTF_INDEX_TO_TYPEPTR(fp, i) \
((i > fp->ctf_stypes) ? \
ctf_dtd_lookup (fp, ctf_index_to_type (fp, i))->dtd_data : \
- (ctf_type_t *)((uintptr_t)(fp)->ctf_buf + (fp)->ctf_txlate[(i)]))
+ (fp)->ctf_txlate[(i)])
/* The non *INFO variants of these macros acquire the relevant info from the
suffixed type, if the type is prefixed. (Internally to libctf, all types
diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c
index 815d1d8..532c5de 100644
--- a/libctf/ctf-lookup.c
+++ b/libctf/ctf-lookup.c
@@ -397,7 +397,7 @@ ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type, const ctf_type_t **suffix)
ctf_set_errno (*fpp, ECTF_BADID);
return NULL;
}
-
+
*fpp = fp; /* Possibly the parent CTF dict. */
if (idx > fp->ctf_stypes)
{
@@ -410,9 +410,8 @@ ctf_lookup_by_id (ctf_dict_t **fpp, ctf_id_t type, const ctf_type_t **suffix)
}
else
{
- ctf_type_t *tp;
-
- tp = (ctf_type_t *)((uintptr_t) fp->ctf_buf + fp->ctf_txlate[idx]);
+ ctf_type_t *tp = fp->ctf_txlate[idx];
+
if (suffix)
{
ctf_type_t *suff;
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index b978db3..a0f7238 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -756,7 +756,7 @@ init_static_types (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
because later-added types will call grow_ptrtab() automatically, as
needed. */
- fp->ctf_txlate = calloc (typemax + 1, sizeof (uint32_t));
+ fp->ctf_txlate = calloc (typemax + 1, sizeof (ctf_type_t *));
fp->ctf_ptrtab = calloc (typemax + 1, sizeof (uint32_t));
fp->ctf_ptrtab_len = typemax + 1;
fp->ctf_stypes = typemax;
@@ -798,6 +798,9 @@ init_static_types_names (ctf_dict_t *fp, ctf_header_t *cth, int is_btf)
return err;
}
+static int
+init_void (ctf_dict_t *fp);
+
/* Initialize the parts of the CTF dict whose initialization depends on name or
type lookup. This happens at open time except for child dicts, when (for
CTFv4+ dicts) it happens at ctf_import time instead, because before then the
@@ -810,16 +813,12 @@ static int
init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
ctf_dynset_t *all_enums)
{
- const ctf_type_t *tbuf;
- const ctf_type_t *tend;
+ ctf_type_t *tbuf, *tend, *tp;
+ ctf_type_t **xp;
- const ctf_type_t *tp;
uint32_t id;
- uint32_t *xp;
ctf_id_t type;
- unsigned long typemax = fp->ctf_typemax;
-
ctf_next_t *i = NULL;
void *k;
int err;
@@ -831,22 +830,14 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
assert (!(fp->ctf_flags & LCTF_NO_STR));
- xp = fp->ctf_txlate;
- *xp++ = 0; /* Type id 0 is used as a sentinel value. */
+ xp = &fp->ctf_txlate[1];
/* In this second pass through the types, we fill in each entry of the type
and pointer tables and add names to the appropriate hashes.
- (Not all names are added in this pass, only type names. See below.)
+ (Not all names are added in this pass, only type names. See below.) */
- Reset ctf_typemax and bump it as we go, but keep it one higher than normal,
- so that the type being read in is considered a valid type and it is at
- least barely possible to run simple lookups on it: but higher types are
- not, since their names are not yet known. (It is kept at its standard
- value before this function is called so that at least some type-related
- operations work. */
-
- for (id = 1, fp->ctf_typemax = 1, tp = tbuf; tp < tend; xp++, id++, fp->ctf_typemax++)
+ for (id = 1, tp = tbuf; tp < tend; xp++, id++)
{
unsigned short kind = LCTF_KIND (fp, tp);
unsigned short isroot = LCTF_INFO_ISROOT (fp, tp->ctt_info);
@@ -871,7 +862,7 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
/* Cannot fail: shielded by call in init_static_types. */
vbytes = LCTF_VBYTES (fp, suffix, size);
- *xp = (uint32_t) ((uintptr_t) tp - (uintptr_t) fp->ctf_buf);
+ *xp = tp;
switch (kind)
{
@@ -1104,10 +1095,12 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
}
tp = (ctf_type_t *) ((uintptr_t) tp + increment + vbytes);
}
- fp->ctf_typemax--;
- assert (fp->ctf_typemax == typemax);
+ assert (fp->ctf_typemax == id - 1);
- ctf_dprintf ("%u total types processed\n", fp->ctf_typemax);
+ ctf_dprintf ("%u total types processed\n", id - 1);
+
+ if ((err = init_void (fp) < 0))
+ return err;
/* In the third pass, we traverse the enums we spotted earlier and track all
the enumeration constants to aid in future detection of duplicates.
@@ -1185,6 +1178,52 @@ init_static_types_names_internal (ctf_dict_t *fp, ctf_header_t *cth, int is_btf,
return 0;
}
+/* Prepare the void type. If present, index 0 is pointed at it: otherwise, we
+ make one in the ctf_void_type member and point index 0 at that. Because this
+ is index 0, it is not written out by serialization (which always starts at
+ index 1): because it is type 0, it is the type expected by BTF consumers:
+ because it is a real, queryable type, CTF consumers will get a proper type
+ back that they can query the properties of.
+
+ As an initialization function, this returns a positive error code, or
+ zero. */
+
+static int
+init_void (ctf_dict_t *fp)
+{
+ ctf_id_t void_type;
+ ctf_type_t *void_tp;
+
+ void_type = ctf_dynhash_lookup_type (ctf_name_table (fp, CTF_K_INTEGER), "void");
+
+ if (void_type == 0)
+ {
+ uint32_t *vlen;
+
+ if ((void_tp = calloc (1, sizeof (ctf_type_t) + sizeof (uint32_t))) == NULL)
+ return ENOMEM;
+ vlen = (uint32_t *) (void_tp + 1);
+
+ void_tp->ctt_name = ctf_str_add (fp, "void");
+ void_tp->ctt_info = CTF_TYPE_INFO (CTF_K_INTEGER, 0, 0);
+ void_tp->ctt_size = 4; /* (bytes) */
+ *vlen = CTF_INT_DATA (CTF_INT_SIGNED, 0, 0);
+
+ fp->ctf_void_type = void_tp;
+ }
+ else
+ {
+ ctf_dict_t *tmp = fp;
+
+ void_tp = (ctf_type_t *) ctf_lookup_by_id (&tmp, void_type, NULL);
+ assert (void_tp != NULL);
+ }
+
+ fp->ctf_txlate[0] = void_tp;
+
+ return 0;
+}
+
/* Endianness-flipping routines.
We flip everything, mindlessly, even 1-byte entities, so that future
@@ -2392,6 +2431,7 @@ ctf_dict_close (ctf_dict_t *fp)
free (err);
}
+ free (fp->ctf_void_type);
free (fp->ctf_sxlate);
free (fp->ctf_txlate);
free (fp->ctf_ptrtab);
@@ -2530,6 +2570,7 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
const char *old_parent_name = fp->ctf_parent_name;
int old_unreffed = fp->ctf_parent_unreffed;
int is_btf = 0;
+ size_t expected_prov_strings = 0;
if (pfp == NULL || pfp == fp->ctf_parent)
return 0;
@@ -2586,16 +2627,22 @@ ctf_import_internal (ctf_dict_t *fp, ctf_dict_t *pfp, int unreffed)
return (ctf_set_errno (fp, EINVAL));
}
fp->ctf_header->cth_parent_ntypes = pfp->ctf_typemax;
+
+ /* We expect one provisional string in this new dict, for the name of
+ the (non-reffed, non-written-out) void type. */
+ expected_prov_strings++;
}
}
- /* We might in time be able to lift this restriction, but it is unlikely to be
- something anyone would want to do, so let's not bother for now. */
+ /* No importing dicts with provisional strings in (except for the void one
+ added to all new dicts). We might in time be able to lift this
+ restriction, but it is unlikely to be something anyone would want to do, so
+ let's not bother for now. */
- if (ctf_dynhash_elements (fp->ctf_prov_strtab) != 0)
+ if (ctf_dynhash_elements (fp->ctf_prov_strtab) != expected_prov_strings)
{
ctf_err_warn (fp, 0, EINVAL,
- _("ctf_import: child dict already has %zi bytes of strings, cannot import"),
+ _("ctf_import: child dict already has %zi strings, cannot import"),
ctf_dynhash_elements (fp->ctf_prov_strtab));
return (ctf_set_errno (fp, EINVAL));
}
diff --git a/libctf/ctf-serialize.c b/libctf/ctf-serialize.c
index 60a6332..9825220 100644
--- a/libctf/ctf-serialize.c
+++ b/libctf/ctf-serialize.c
@@ -1248,8 +1248,9 @@ ctf_emit_type_sect (ctf_dict_t *fp, unsigned char **tptr)
}
#ifdef ENABLE_LIBCTF_HASH_DEBUGGING
- ctf_dprintf ("%p: provisional ID assignment: %lx -> %lx\n", (void *) fp,
- dtd->dtd_type, id);
+ if (dtd->dtd_type != id)
+ ctf_dprintf ("%p: provisional ID assignment: %lx -> %lx\n", (void *) fp,
+ dtd->dtd_type, id);
#endif
t += dtd->dtd_vlen_size;
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 3ef897f..b42d047 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -618,7 +618,7 @@ ctf_type_next (ctf_dict_t *fp, ctf_next_t **it, int *flag, int want_hidden)
if (i->ctn_type > fp->ctf_stypes)
tp = ctf_dtd_lookup (fp, ctf_index_to_type (fp, i->ctn_type))->dtd_data;
else
- tp = (ctf_type_t *)((uintptr_t) fp->ctf_buf + fp->ctf_txlate[i->ctn_type]);
+ tp = fp->ctf_txlate[i->ctn_type];
if ((!want_hidden) && (!LCTF_INFO_ISROOT (fp, tp->ctt_info)))
{
diff --git a/libctf/testsuite/libctf-lookup/by-kind/array.lk b/libctf/testsuite/libctf-lookup/by-kind/array.lk
index 49e1280..7263af2 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/array.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/array.lk
@@ -11,5 +11,5 @@ Types:
0x1: \(kind 1\) int .*
0x2: \(kind 1\) long unsigned int .*
0x3: \(kind 3\) int \[16\] .*
-0x4: \(kind 14\) foo .*
+0x4: \(kind 14\) int foo .*
0x5: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/const.lk b/libctf/testsuite/libctf-lookup/by-kind/const.lk
index ff0adfa..a7fe4fe 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/const.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/const.lk
@@ -10,5 +10,5 @@ Types:
0x1: \(kind 1\) int .*
0x2: \(kind 10\) const int .*
-0x3: \(kind 14\) foo .*
+0x3: \(kind 14\) const int foo .*
0x4: \(kind 15\) DATASEC \(".rodata"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/datasec.lk b/libctf/testsuite/libctf-lookup/by-kind/datasec.lk
index 86a6442..3014837 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/datasec.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/datasec.lk
@@ -9,6 +9,6 @@ Section \.BAR:
Types:
0x1: \(kind 1\) int .*
-0x2: \(kind 14\) foo .*
+0x2: \(kind 14\) int foo .*
0x3: \(kind 15\) DATASEC \(".BAR"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/decl-tag.lk b/libctf/testsuite/libctf-lookup/by-kind/decl-tag.lk
index 3dbae5a..18c430a 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/decl-tag.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/decl-tag.lk
@@ -15,9 +15,9 @@ Types:
\[0x8\] b: ID 0x3: \(kind 1\) char .*
0x3: \(kind 1\) char .*
#...
-0x[45]: \(kind 14\) bar .*
+0x[45]: \(kind 14\) struct bar .*
#...
-0x[56]: \(kind 14\) foo .*
-0x[67]: \(kind 17\) btf_decl_tag \("dtag"\) .* -> 0x[56]: \(kind 14\) foo .*
-0x[78]: \(kind 17\) btf_decl_tag \("dtag2"\) .* -> 0x2: \(kind 4\) struct .*
+0x[56]: \(kind 14\) int foo .*
+0x[67]: \(kind 17\) int foo btf_decl_tag \("dtag"\) .* -> 0x[56]: \(kind 14\) int foo .*
+0x[78]: \(kind 17\) struct btf_decl_tag \("dtag2"\) .* -> 0x2: \(kind 4\) struct .*
#...
diff --git a/libctf/testsuite/libctf-lookup/by-kind/forward.lk b/libctf/testsuite/libctf-lookup/by-kind/forward.lk
index e66396e..0cf3b03 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/forward.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/forward.lk
@@ -10,5 +10,5 @@ Types:
0x1: \(kind 7\) struct foo
0x2: \(kind 2\) struct foo \* .* -> 0x1: \(kind 7\) struct foo
-0x3: \(kind 14\) bar .* -> 0x2: \(kind 2\) struct foo \* .* -> 0x1: \(kind 7\) struct foo
+0x3: \(kind 14\) struct foo bar .* -> 0x2: \(kind 2\) struct foo \* .* -> 0x1: \(kind 7\) struct foo
0x4: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/integer.lk b/libctf/testsuite/libctf-lookup/by-kind/integer.lk
index 09eb345..5fa7ce6 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/integer.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/integer.lk
@@ -9,5 +9,5 @@ Section \.bss:
Types:
0x1: \(kind 1\) int .*
-0x2: \(kind 14\) foo .*
+0x2: \(kind 14\) int foo .*
0x3: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/pointer.lk b/libctf/testsuite/libctf-lookup/by-kind/pointer.lk
index dba2e40..a60ba49 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/pointer.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/pointer.lk
@@ -10,5 +10,5 @@ Types:
0x1: \(kind 1\) int .*
0x2: \(kind 2\) int \* .*
-0x3: \(kind 14\) foo .*
+0x3: \(kind 14\) int foo .*
0x4: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/restrict.lk b/libctf/testsuite/libctf-lookup/by-kind/restrict.lk
index 0783778..f6f27b0 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/restrict.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/restrict.lk
@@ -11,5 +11,5 @@ Types:
0x1: \(kind 1\) int .*
0x2: \(kind 2\) int \* .*
0x3: \(kind 11\) int \*restrict .*
-0x4: \(kind 14\) foo .*
+0x4: \(kind 14\) int foo .*
0x5: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/struct.lk b/libctf/testsuite/libctf-lookup/by-kind/struct.lk
index 2fd0581..b5fc264 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/struct.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/struct.lk
@@ -13,5 +13,5 @@ Types:
\[0x4\] b:4: .* int .*
\[0x[0-9a-f]*\] c: .* int .*
0x2: \(kind 1\) int .*
-0x3: \(kind 14\) foo .*
+0x3: \(kind 14\) struct foo .*
0x4: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/union.lk b/libctf/testsuite/libctf-lookup/by-kind/union.lk
index b37477c..b2d97f7 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/union.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/union.lk
@@ -13,5 +13,5 @@ Types:
\[0x0\] b:4: .* int .*
\[0x0\] c: .* int .*
0x2: \(kind 1\) int .*
-0x3: \(kind 14\) foo .*
+0x3: \(kind 14\) union bar foo .*
0x4: \(kind 15\) DATASEC \(".bss"\)
diff --git a/libctf/testsuite/libctf-lookup/by-kind/volatile.lk b/libctf/testsuite/libctf-lookup/by-kind/volatile.lk
index c4af120..fbd5faa 100644
--- a/libctf/testsuite/libctf-lookup/by-kind/volatile.lk
+++ b/libctf/testsuite/libctf-lookup/by-kind/volatile.lk
@@ -10,5 +10,5 @@ Types:
0x1: \(kind 1\) int .*
0x2: \(kind 9\) volatile int .*
-0x3: \(kind 14\) foo .*
+0x3: \(kind 14\) volatile int foo .*
0x4: \(kind 15\) DATASEC \(".bss"\)