|
|
5022a5 |
commit f701ecad0f4b8d54b80455774b3ce4e328725a1b
|
|
|
5022a5 |
Author: Dave Anderson <anderson@redhat.com>
|
|
|
5022a5 |
Date: Wed Nov 7 12:02:51 2018 -0500
|
|
|
5022a5 |
|
|
|
5022a5 |
Implemented the functionality for a new MEMBER_TYPE_NAME() macro,
|
|
|
5022a5 |
which will return a pointer to the type name string of a structure
|
|
|
5022a5 |
member. It is being put in place for the support of Linux 4.20
|
|
|
5022a5 |
radix tree to xarray replacements, where structure member types may
|
|
|
5022a5 |
be changed from radix_tree_root structures to xarray structures.
|
|
|
5022a5 |
(anderson@redhat.com)
|
|
|
5022a5 |
|
|
|
5022a5 |
diff --git a/defs.h b/defs.h
|
|
|
5022a5 |
index bea70c5899ef..e8ade5778dd1 100644
|
|
|
5022a5 |
--- a/defs.h
|
|
|
5022a5 |
+++ b/defs.h
|
|
|
5022a5 |
@@ -2232,6 +2232,7 @@ struct array_table {
|
|
|
5022a5 |
#define ANON_MEMBER_OFFSET_REQUEST ((struct datatype_member *)(-2))
|
|
|
5022a5 |
#define MEMBER_TYPE_REQUEST ((struct datatype_member *)(-3))
|
|
|
5022a5 |
#define STRUCT_SIZE_REQUEST ((struct datatype_member *)(-4))
|
|
|
5022a5 |
+#define MEMBER_TYPE_NAME_REQUEST ((struct datatype_member *)(-5))
|
|
|
5022a5 |
|
|
|
5022a5 |
#define STRUCT_SIZE(X) datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
|
|
|
5022a5 |
#define UNION_SIZE(X) datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
|
|
|
5022a5 |
@@ -2241,6 +2242,7 @@ struct array_table {
|
|
|
5022a5 |
#define MEMBER_EXISTS(X,Y) (datatype_info((X), (Y), NULL) >= 0)
|
|
|
5022a5 |
#define MEMBER_SIZE(X,Y) datatype_info((X), (Y), MEMBER_SIZE_REQUEST)
|
|
|
5022a5 |
#define MEMBER_TYPE(X,Y) datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
|
|
|
5022a5 |
+#define MEMBER_TYPE_NAME(X,Y) ((char *)datatype_info((X), (Y), MEMBER_TYPE_NAME_REQUEST))
|
|
|
5022a5 |
#define ANON_MEMBER_OFFSET(X,Y) datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST)
|
|
|
5022a5 |
|
|
|
5022a5 |
/*
|
|
|
5022a5 |
@@ -4546,6 +4548,10 @@ struct gnu_request {
|
|
|
5022a5 |
struct objfile *obj;
|
|
|
5022a5 |
} global_iterator;
|
|
|
5022a5 |
struct load_module *lm;
|
|
|
5022a5 |
+ char *member_main_type_name;
|
|
|
5022a5 |
+ char *member_main_type_tag_name;
|
|
|
5022a5 |
+ char *member_target_type_name;
|
|
|
5022a5 |
+ char *member_target_type_tag_name;
|
|
|
5022a5 |
};
|
|
|
5022a5 |
|
|
|
5022a5 |
/*
|
|
|
5022a5 |
diff --git a/gdb-7.6.patch b/gdb-7.6.patch
|
|
|
5022a5 |
index ec63c0df82b9..87447fa44094 100644
|
|
|
5022a5 |
--- a/gdb-7.6.patch
|
|
|
5022a5 |
+++ b/gdb-7.6.patch
|
|
|
5022a5 |
@@ -2407,3 +2407,28 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure
|
|
|
5022a5 |
#include <sys/ptrace.h>
|
|
|
5022a5 |
#include <asm/types.h>
|
|
|
5022a5 |
#include <sys/procfs.h>
|
|
|
5022a5 |
+--- gdb-7.6/gdb/symtab.c.orig
|
|
|
5022a5 |
++++ gdb-7.6/gdb/symtab.c
|
|
|
5022a5 |
+@@ -5500,7 +5500,7 @@ get_member_data(struct gnu_request *req,
|
|
|
5022a5 |
+ register short i;
|
|
|
5022a5 |
+ struct field *nextfield;
|
|
|
5022a5 |
+ short nfields;
|
|
|
5022a5 |
+- struct type *typedef_type;
|
|
|
5022a5 |
++ struct type *typedef_type, *target_type;
|
|
|
5022a5 |
+
|
|
|
5022a5 |
+ req->member_offset = -1;
|
|
|
5022a5 |
+
|
|
|
5022a5 |
+@@ -5523,6 +5523,13 @@ get_member_data(struct gnu_request *req,
|
|
|
5022a5 |
+ req->member_offset = offset + nextfield->loc.bitpos;
|
|
|
5022a5 |
+ req->member_length = TYPE_LENGTH(nextfield->type);
|
|
|
5022a5 |
+ req->member_typecode = TYPE_CODE(nextfield->type);
|
|
|
5022a5 |
++ req->member_main_type_name = (char *)TYPE_NAME(nextfield->type);
|
|
|
5022a5 |
++ req->member_main_type_tag_name = (char *)TYPE_TAG_NAME(nextfield->type);
|
|
|
5022a5 |
++ target_type = TYPE_TARGET_TYPE(nextfield->type);
|
|
|
5022a5 |
++ if (target_type) {
|
|
|
5022a5 |
++ req->member_target_type_name = (char *)TYPE_NAME(target_type);
|
|
|
5022a5 |
++ req->member_target_type_tag_name = (char *)TYPE_TAG_NAME(target_type);
|
|
|
5022a5 |
++ }
|
|
|
5022a5 |
+ if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
|
|
|
5022a5 |
+ (typedef_type = check_typedef(nextfield->type)))
|
|
|
5022a5 |
+ req->member_length = TYPE_LENGTH(typedef_type);
|
|
|
5022a5 |
diff --git a/gdb_interface.c b/gdb_interface.c
|
|
|
5022a5 |
index 3cf99c1b6529..608da86058c2 100755
|
|
|
5022a5 |
--- a/gdb_interface.c
|
|
|
5022a5 |
+++ b/gdb_interface.c
|
|
|
5022a5 |
@@ -512,6 +512,10 @@ dump_gnu_request(struct gnu_request *req, int in_gdb)
|
|
|
5022a5 |
console("member_offset: %ld\n", req->member_offset);
|
|
|
5022a5 |
console("member_length: %ld\n", req->member_length);
|
|
|
5022a5 |
console("member_typecode: %d\n", req->member_typecode);
|
|
|
5022a5 |
+ console("member_main_type_name: %s\n", req->member_main_type_name);
|
|
|
5022a5 |
+ console("member_main_type_tag_name: %s\n", req->member_main_type_tag_name);
|
|
|
5022a5 |
+ console("member_target_type_name: %s\n", req->member_target_type_name);
|
|
|
5022a5 |
+ console("member_target_type_tag_name: %s\n", req->member_target_type_tag_name);
|
|
|
5022a5 |
console("value: %lx ", req->value);
|
|
|
5022a5 |
console("tagname: \"%s\" ", req->tagname);
|
|
|
5022a5 |
console("pc: %lx ", req->pc);
|
|
|
5022a5 |
diff --git a/symbols.c b/symbols.c
|
|
|
5022a5 |
index 7966f129f80f..b1164613e342 100644
|
|
|
5022a5 |
--- a/symbols.c
|
|
|
5022a5 |
+++ b/symbols.c
|
|
|
5022a5 |
@@ -5447,6 +5447,7 @@ datatype_init(void)
|
|
|
5022a5 |
* #define MEMBER_EXISTS(X,Y) (datatype_info((X), (Y), NULL) >= 0)
|
|
|
5022a5 |
* #define MEMBER_SIZE(X,Y) datatype_info((X), (Y), MEMBER_SIZE_REQUEST)
|
|
|
5022a5 |
* #define MEMBER_TYPE(X,Y) datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
|
|
|
5022a5 |
+ * #define MEMBER_TYPE_NAME(X,Y) datatype_info((X), (Y), MEMBER_TYPE_NAME_REQUEST)
|
|
|
5022a5 |
* #define ANON_MEMBER_OFFSET(X,Y) datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST)
|
|
|
5022a5 |
*
|
|
|
5022a5 |
* to determine structure or union sizes, or member offsets.
|
|
|
5022a5 |
@@ -5473,9 +5474,9 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
|
|
|
5022a5 |
req->fp = pc->nullfp;
|
|
|
5022a5 |
|
|
|
5022a5 |
gdb_interface(req);
|
|
|
5022a5 |
- if (req->flags & GNU_COMMAND_FAILED) {
|
|
|
5022a5 |
+ if (req->flags & GNU_COMMAND_FAILED) {
|
|
|
5022a5 |
FREEBUF(req);
|
|
|
5022a5 |
- return -1;
|
|
|
5022a5 |
+ return (dm == MEMBER_TYPE_NAME_REQUEST) ? 0 : -1;
|
|
|
5022a5 |
}
|
|
|
5022a5 |
|
|
|
5022a5 |
if (!req->typecode) {
|
|
|
5022a5 |
@@ -5591,7 +5592,7 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
|
|
|
5022a5 |
FREEBUF(req);
|
|
|
5022a5 |
|
|
|
5022a5 |
if (dm && (dm != MEMBER_SIZE_REQUEST) && (dm != MEMBER_TYPE_REQUEST) &&
|
|
|
5022a5 |
- (dm != STRUCT_SIZE_REQUEST)) {
|
|
|
5022a5 |
+ (dm != STRUCT_SIZE_REQUEST) && (dm != MEMBER_TYPE_NAME_REQUEST)) {
|
|
|
5022a5 |
dm->type = type_found;
|
|
|
5022a5 |
dm->size = size;
|
|
|
5022a5 |
dm->member_size = member_size;
|
|
|
5022a5 |
@@ -5606,14 +5607,25 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
|
|
|
5022a5 |
}
|
|
|
5022a5 |
}
|
|
|
5022a5 |
|
|
|
5022a5 |
- if (!type_found)
|
|
|
5022a5 |
- return -1;
|
|
|
5022a5 |
+ if (!type_found)
|
|
|
5022a5 |
+ return (dm == MEMBER_TYPE_NAME_REQUEST) ? 0 : -1;
|
|
|
5022a5 |
|
|
|
5022a5 |
if (dm == MEMBER_SIZE_REQUEST)
|
|
|
5022a5 |
return member_size;
|
|
|
5022a5 |
else if (dm == MEMBER_TYPE_REQUEST)
|
|
|
5022a5 |
return member_typecode;
|
|
|
5022a5 |
- else if (dm == STRUCT_SIZE_REQUEST) {
|
|
|
5022a5 |
+ else if (dm == MEMBER_TYPE_NAME_REQUEST) {
|
|
|
5022a5 |
+ if (req->member_main_type_name)
|
|
|
5022a5 |
+ return (ulong)req->member_main_type_name;
|
|
|
5022a5 |
+ else if (req->member_main_type_tag_name)
|
|
|
5022a5 |
+ return (ulong)req->member_main_type_tag_name;
|
|
|
5022a5 |
+ else if (req->member_target_type_name)
|
|
|
5022a5 |
+ return (ulong)req->member_target_type_name;
|
|
|
5022a5 |
+ else if (req->member_target_type_tag_name)
|
|
|
5022a5 |
+ return (ulong)req->member_target_type_tag_name;
|
|
|
5022a5 |
+ else
|
|
|
5022a5 |
+ return 0;
|
|
|
5022a5 |
+ } else if (dm == STRUCT_SIZE_REQUEST) {
|
|
|
5022a5 |
if ((req->typecode == TYPE_CODE_STRUCT) ||
|
|
|
5022a5 |
(req->typecode == TYPE_CODE_UNION) ||
|
|
|
5022a5 |
req->is_typedef)
|
|
|
5022a5 |
commit a812e59a175c8c6197ae3dc78bd5e1613adcc57c
|
|
|
5022a5 |
Author: Dave Anderson <anderson@redhat.com>
|
|
|
5022a5 |
Date: Fri Aug 2 12:03:40 2019 -0400
|
|
|
5022a5 |
|
|
|
5022a5 |
Fix for the "timer" command in RHEL7.6 and later RHEL7 kernels.
|
|
|
5022a5 |
Without the patch, the command emits extra faulty timer entries
|
|
|
5022a5 |
because the tvec_root.vec[] and tvec.vec[] arrays are tracked using
|
|
|
5022a5 |
hlist_head structures where list_head structures should be used.
|
|
|
5022a5 |
(k-hagio@ab.jp.nec.com)
|
|
|
5022a5 |
|
|
|
5022a5 |
diff --git a/kernel.c b/kernel.c
|
|
|
5022a5 |
index 3cd5bf1aab73..1ef063226041 100644
|
|
|
5022a5 |
--- a/kernel.c
|
|
|
5022a5 |
+++ b/kernel.c
|
|
|
5022a5 |
@@ -53,7 +53,7 @@ static void dump_timer_data_timer_bases(const ulong *cpus);
|
|
|
5022a5 |
struct tv_range;
|
|
|
5022a5 |
static void init_tv_ranges(struct tv_range *, int, int, int);
|
|
|
5022a5 |
static int do_timer_list(ulong,int, ulong *, void *,ulong *,struct tv_range *);
|
|
|
5022a5 |
-static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *);
|
|
|
5022a5 |
+static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *, long);
|
|
|
5022a5 |
struct timer_bases_data;
|
|
|
5022a5 |
static int do_timer_list_v4(struct timer_bases_data *);
|
|
|
5022a5 |
static int compare_timer_data(const void *, const void *);
|
|
|
5022a5 |
@@ -8237,7 +8237,12 @@ dump_timer_data_tvec_bases_v3(const ulong *cpus)
|
|
|
5022a5 |
char buf3[BUFSIZE];
|
|
|
5022a5 |
|
|
|
5022a5 |
vec_root_size = vec_size = 0;
|
|
|
5022a5 |
- head_size = SIZE(hlist_head);
|
|
|
5022a5 |
+
|
|
|
5022a5 |
+ if (STREQ(MEMBER_TYPE_NAME("tvec_root", "vec"), "list_head"))
|
|
|
5022a5 |
+ /* for RHEL7.6 or later */
|
|
|
5022a5 |
+ head_size = SIZE(list_head);
|
|
|
5022a5 |
+ else
|
|
|
5022a5 |
+ head_size = SIZE(hlist_head);
|
|
|
5022a5 |
|
|
|
5022a5 |
if ((i = get_array_length("tvec_root.vec", NULL, head_size)))
|
|
|
5022a5 |
vec_root_size = i;
|
|
|
5022a5 |
@@ -8275,15 +8280,15 @@ next_cpu:
|
|
|
5022a5 |
init_tv_ranges(tv, vec_root_size, vec_size, cpu);
|
|
|
5022a5 |
|
|
|
5022a5 |
count += do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
|
|
|
5022a5 |
- vec_root_size, vec, NULL, NULL);
|
|
|
5022a5 |
+ vec_root_size, vec, NULL, NULL, head_size);
|
|
|
5022a5 |
count += do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, NULL, NULL);
|
|
|
5022a5 |
+ vec_size, vec, NULL, NULL, head_size);
|
|
|
5022a5 |
count += do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, NULL, NULL);
|
|
|
5022a5 |
+ vec_size, vec, NULL, NULL, head_size);
|
|
|
5022a5 |
count += do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, NULL, NULL);
|
|
|
5022a5 |
+ vec_size, vec, NULL, NULL, head_size);
|
|
|
5022a5 |
count += do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, NULL, NULL);
|
|
|
5022a5 |
+ vec_size, vec, NULL, NULL, head_size);
|
|
|
5022a5 |
|
|
|
5022a5 |
if (count)
|
|
|
5022a5 |
td = (struct timer_data *)
|
|
|
5022a5 |
@@ -8293,15 +8298,15 @@ next_cpu:
|
|
|
5022a5 |
get_symbol_data("jiffies", sizeof(ulong), &jiffies);
|
|
|
5022a5 |
|
|
|
5022a5 |
do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
|
|
|
5022a5 |
- vec_root_size, vec, (void *)td, &highest);
|
|
|
5022a5 |
+ vec_root_size, vec, (void *)td, &highest, head_size);
|
|
|
5022a5 |
do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, (void *)td, &highest);
|
|
|
5022a5 |
+ vec_size, vec, (void *)td, &highest, head_size);
|
|
|
5022a5 |
do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, (void *)td, &highest);
|
|
|
5022a5 |
+ vec_size, vec, (void *)td, &highest, head_size);
|
|
|
5022a5 |
do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, (void *)td, &highest);
|
|
|
5022a5 |
+ vec_size, vec, (void *)td, &highest, head_size);
|
|
|
5022a5 |
tdx = do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
|
|
|
5022a5 |
- vec_size, vec, (void *)td, &highest);
|
|
|
5022a5 |
+ vec_size, vec, (void *)td, &highest, head_size);
|
|
|
5022a5 |
|
|
|
5022a5 |
qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
|
|
|
5022a5 |
|
|
|
5022a5 |
@@ -8627,7 +8632,8 @@ do_timer_list_v3(ulong vec_kvaddr,
|
|
|
5022a5 |
int size,
|
|
|
5022a5 |
ulong *vec,
|
|
|
5022a5 |
void *option,
|
|
|
5022a5 |
- ulong *highest)
|
|
|
5022a5 |
+ ulong *highest,
|
|
|
5022a5 |
+ long head_size)
|
|
|
5022a5 |
{
|
|
|
5022a5 |
int i, t;
|
|
|
5022a5 |
int count, tdx;
|
|
|
5022a5 |
@@ -8645,19 +8651,24 @@ do_timer_list_v3(ulong vec_kvaddr,
|
|
|
5022a5 |
tdx++;
|
|
|
5022a5 |
}
|
|
|
5022a5 |
|
|
|
5022a5 |
- readmem(vec_kvaddr, KVADDR, vec, SIZE(hlist_head) * size,
|
|
|
5022a5 |
+ readmem(vec_kvaddr, KVADDR, vec, head_size * size,
|
|
|
5022a5 |
"timer_list vec array", FAULT_ON_ERROR);
|
|
|
5022a5 |
|
|
|
5022a5 |
ld = &list_data;
|
|
|
5022a5 |
timer_list_buf = GETBUF(SIZE(timer_list));
|
|
|
5022a5 |
|
|
|
5022a5 |
- for (i = count = 0; i < size; i++, vec_kvaddr += SIZE(hlist_head)) {
|
|
|
5022a5 |
+ for (i = count = 0; i < size; i++, vec_kvaddr += head_size) {
|
|
|
5022a5 |
|
|
|
5022a5 |
- if (vec[i] == 0)
|
|
|
5022a5 |
- continue;
|
|
|
5022a5 |
+ if (head_size == SIZE(list_head)) {
|
|
|
5022a5 |
+ if (vec[i*2] == vec_kvaddr)
|
|
|
5022a5 |
+ continue;
|
|
|
5022a5 |
+ } else {
|
|
|
5022a5 |
+ if (vec[i] == 0)
|
|
|
5022a5 |
+ continue;
|
|
|
5022a5 |
+ }
|
|
|
5022a5 |
|
|
|
5022a5 |
BZERO(ld, sizeof(struct list_data));
|
|
|
5022a5 |
- ld->start = vec[i];
|
|
|
5022a5 |
+ ld->start = (head_size == SIZE(list_head)) ? vec[i*2] : vec[i];
|
|
|
5022a5 |
ld->list_head_offset = OFFSET(timer_list_entry);
|
|
|
5022a5 |
ld->end = vec_kvaddr;
|
|
|
5022a5 |
ld->flags = RETURN_ON_LIST_ERROR;
|
|
|
5022a5 |
|