Blame SOURCES/github_f701ecad_a812e59a_timer_rhel7.6.patch

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