Blob Blame History Raw
commit f701ecad0f4b8d54b80455774b3ce4e328725a1b
Author: Dave Anderson <anderson@redhat.com>
Date:   Wed Nov 7 12:02:51 2018 -0500

    Implemented the functionality for a new MEMBER_TYPE_NAME() macro,
    which will return a pointer to the type name string of a structure
    member.  It is being put in place for the support of Linux 4.20
    radix tree to xarray replacements, where structure member types may
    be changed from radix_tree_root structures to xarray structures.
    (anderson@redhat.com)

diff --git a/defs.h b/defs.h
index bea70c5899ef..e8ade5778dd1 100644
--- a/defs.h
+++ b/defs.h
@@ -2232,6 +2232,7 @@ struct array_table {
 #define ANON_MEMBER_OFFSET_REQUEST ((struct datatype_member *)(-2))
 #define MEMBER_TYPE_REQUEST ((struct datatype_member *)(-3))
 #define STRUCT_SIZE_REQUEST ((struct datatype_member *)(-4))
+#define MEMBER_TYPE_NAME_REQUEST ((struct datatype_member *)(-5))
 
 #define STRUCT_SIZE(X)      datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
 #define UNION_SIZE(X)       datatype_info((X), NULL, STRUCT_SIZE_REQUEST)
@@ -2241,6 +2242,7 @@ struct array_table {
 #define MEMBER_EXISTS(X,Y)  (datatype_info((X), (Y), NULL) >= 0)
 #define MEMBER_SIZE(X,Y)    datatype_info((X), (Y), MEMBER_SIZE_REQUEST)
 #define MEMBER_TYPE(X,Y)    datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
+#define MEMBER_TYPE_NAME(X,Y)    ((char *)datatype_info((X), (Y), MEMBER_TYPE_NAME_REQUEST))
 #define ANON_MEMBER_OFFSET(X,Y)    datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST)
 
 /*
@@ -4546,6 +4548,10 @@ struct gnu_request {
     		struct objfile *obj;
   	} global_iterator;
 	struct load_module *lm;
+	char *member_main_type_name;
+	char *member_main_type_tag_name;
+	char *member_target_type_name;
+	char *member_target_type_tag_name;
 };
 
 /*
diff --git a/gdb-7.6.patch b/gdb-7.6.patch
index ec63c0df82b9..87447fa44094 100644
--- a/gdb-7.6.patch
+++ b/gdb-7.6.patch
@@ -2407,3 +2407,28 @@ diff -up gdb-7.6/opcodes/configure.orig gdb-7.6/opcodes/configure
  #include <sys/ptrace.h>
  #include <asm/types.h>
  #include <sys/procfs.h>
+--- gdb-7.6/gdb/symtab.c.orig
++++ gdb-7.6/gdb/symtab.c
+@@ -5500,7 +5500,7 @@ get_member_data(struct gnu_request *req,
+ 	register short i;
+ 	struct field *nextfield;
+ 	short nfields;
+-	struct type *typedef_type;
++	struct type *typedef_type, *target_type;
+ 
+ 	req->member_offset = -1;
+ 
+@@ -5523,6 +5523,13 @@ get_member_data(struct gnu_request *req,
+ 			req->member_offset = offset + nextfield->loc.bitpos;
+ 			req->member_length = TYPE_LENGTH(nextfield->type);
+ 			req->member_typecode = TYPE_CODE(nextfield->type);
++			req->member_main_type_name = (char *)TYPE_NAME(nextfield->type);
++			req->member_main_type_tag_name = (char *)TYPE_TAG_NAME(nextfield->type);
++			target_type = TYPE_TARGET_TYPE(nextfield->type);
++			if (target_type) {
++				req->member_target_type_name = (char *)TYPE_NAME(target_type);
++				req->member_target_type_tag_name = (char *)TYPE_TAG_NAME(target_type);
++			}
+ 			if ((req->member_typecode == TYPE_CODE_TYPEDEF) &&
+ 			    (typedef_type = check_typedef(nextfield->type))) 
+         			req->member_length = TYPE_LENGTH(typedef_type);
diff --git a/gdb_interface.c b/gdb_interface.c
index 3cf99c1b6529..608da86058c2 100755
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -512,6 +512,10 @@ dump_gnu_request(struct gnu_request *req, int in_gdb)
 	console("member_offset: %ld\n", req->member_offset);
 	console("member_length: %ld\n", req->member_length);
         console("member_typecode: %d\n", req->member_typecode);
+	console("member_main_type_name: %s\n", req->member_main_type_name);
+	console("member_main_type_tag_name: %s\n", req->member_main_type_tag_name);
+	console("member_target_type_name: %s\n", req->member_target_type_name);
+	console("member_target_type_tag_name: %s\n", req->member_target_type_tag_name);
 	console("value: %lx ", req->value);
 	console("tagname: \"%s\" ", req->tagname);
 	console("pc: %lx  ", req->pc);
diff --git a/symbols.c b/symbols.c
index 7966f129f80f..b1164613e342 100644
--- a/symbols.c
+++ b/symbols.c
@@ -5447,6 +5447,7 @@ datatype_init(void)
  *   #define MEMBER_EXISTS(X,Y)  (datatype_info((X), (Y), NULL) >= 0)
  *   #define MEMBER_SIZE(X,Y)    datatype_info((X), (Y), MEMBER_SIZE_REQUEST)
  *   #define MEMBER_TYPE(X,Y)    datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
+ *   #define MEMBER_TYPE_NAME(X,Y)      datatype_info((X), (Y), MEMBER_TYPE_NAME_REQUEST)
  *   #define ANON_MEMBER_OFFSET(X,Y)    datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST)
  *
  *  to determine structure or union sizes, or member offsets.
@@ -5473,9 +5474,9 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
 	req->fp = pc->nullfp;
 
 	gdb_interface(req);
-        if (req->flags & GNU_COMMAND_FAILED) {
+	if (req->flags & GNU_COMMAND_FAILED) {
 		FREEBUF(req);
-		return -1;
+		return (dm == MEMBER_TYPE_NAME_REQUEST) ? 0 : -1;
 	}
 
 	if (!req->typecode) {
@@ -5591,7 +5592,7 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
 	FREEBUF(req);
 
         if (dm && (dm != MEMBER_SIZE_REQUEST) && (dm != MEMBER_TYPE_REQUEST) &&
-	    (dm != STRUCT_SIZE_REQUEST)) {
+	    (dm != STRUCT_SIZE_REQUEST) && (dm != MEMBER_TYPE_NAME_REQUEST)) {
                 dm->type = type_found;
                 dm->size = size;
 		dm->member_size = member_size;
@@ -5606,14 +5607,25 @@ datatype_info(char *name, char *member, struct datatype_member *dm)
 		}
         }
 
-        if (!type_found) 
-        	return -1;
+	if (!type_found) 
+		return (dm == MEMBER_TYPE_NAME_REQUEST) ? 0 : -1;
 
 	if (dm == MEMBER_SIZE_REQUEST)
 		return member_size;
 	else if (dm == MEMBER_TYPE_REQUEST)
 		return member_typecode;
-	else if (dm == STRUCT_SIZE_REQUEST) {
+	else if (dm == MEMBER_TYPE_NAME_REQUEST) {
+		if (req->member_main_type_name)
+			return (ulong)req->member_main_type_name;
+		else if (req->member_main_type_tag_name)
+			return (ulong)req->member_main_type_tag_name;
+		else if (req->member_target_type_name)
+			return (ulong)req->member_target_type_name;
+		else if (req->member_target_type_tag_name)
+			return (ulong)req->member_target_type_tag_name;
+		else
+			return 0;
+	} else if (dm == STRUCT_SIZE_REQUEST) {
 		if ((req->typecode == TYPE_CODE_STRUCT) || 
 		    (req->typecode == TYPE_CODE_UNION) ||
 		     req->is_typedef)
commit a812e59a175c8c6197ae3dc78bd5e1613adcc57c
Author: Dave Anderson <anderson@redhat.com>
Date:   Fri Aug 2 12:03:40 2019 -0400

    Fix for the "timer" command in RHEL7.6 and later RHEL7 kernels.
    Without the patch, the command emits extra faulty timer entries
    because the tvec_root.vec[] and tvec.vec[] arrays are tracked using
    hlist_head structures where list_head structures should be used.
    (k-hagio@ab.jp.nec.com)

diff --git a/kernel.c b/kernel.c
index 3cd5bf1aab73..1ef063226041 100644
--- a/kernel.c
+++ b/kernel.c
@@ -53,7 +53,7 @@ static void dump_timer_data_timer_bases(const ulong *cpus);
 struct tv_range;
 static void init_tv_ranges(struct tv_range *, int, int, int);
 static int do_timer_list(ulong,int, ulong *, void *,ulong *,struct tv_range *);
-static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *);
+static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *, long);
 struct timer_bases_data;
 static int do_timer_list_v4(struct timer_bases_data *);
 static int compare_timer_data(const void *, const void *);
@@ -8237,7 +8237,12 @@ dump_timer_data_tvec_bases_v3(const ulong *cpus)
 	char buf3[BUFSIZE];
 
 	vec_root_size = vec_size = 0;
-	head_size = SIZE(hlist_head);
+
+	if (STREQ(MEMBER_TYPE_NAME("tvec_root", "vec"), "list_head"))
+		/* for RHEL7.6 or later */
+		head_size = SIZE(list_head);
+	else
+		head_size = SIZE(hlist_head);
 
 	if ((i = get_array_length("tvec_root.vec", NULL, head_size)))
 		vec_root_size = i;
@@ -8275,15 +8280,15 @@ next_cpu:
 	init_tv_ranges(tv, vec_root_size, vec_size, cpu);
 
 	count += do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-		vec_root_size, vec, NULL, NULL);
+		vec_root_size, vec, NULL, NULL, head_size);
 	count += do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, head_size);
 	count += do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, head_size);
 	count += do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, head_size);
 	count += do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-		vec_size, vec, NULL, NULL);
+		vec_size, vec, NULL, NULL, head_size);
 
 	if (count)
 		td = (struct timer_data *)
@@ -8293,15 +8298,15 @@ next_cpu:
 	get_symbol_data("jiffies", sizeof(ulong), &jiffies);
 
 	do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-		vec_root_size, vec, (void *)td, &highest);
+		vec_root_size, vec, (void *)td, &highest, head_size);
 	do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, head_size);
 	do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, head_size);
 	do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, head_size);
 	tdx = do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-		vec_size, vec, (void *)td, &highest);
+		vec_size, vec, (void *)td, &highest, head_size);
 
 	qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -8627,7 +8632,8 @@ do_timer_list_v3(ulong vec_kvaddr,
 	      int size, 
 	      ulong *vec, 
 	      void *option, 
-	      ulong *highest)
+	      ulong *highest,
+	      long head_size)
 {
 	int i, t; 
 	int count, tdx;
@@ -8645,19 +8651,24 @@ do_timer_list_v3(ulong vec_kvaddr,
 			tdx++;
 	}
 
-	readmem(vec_kvaddr, KVADDR, vec, SIZE(hlist_head) * size, 
+	readmem(vec_kvaddr, KVADDR, vec, head_size * size,
 		"timer_list vec array", FAULT_ON_ERROR);
 
 	ld = &list_data;
 	timer_list_buf = GETBUF(SIZE(timer_list));
 
-	for (i = count = 0; i < size; i++, vec_kvaddr += SIZE(hlist_head)) {
+	for (i = count = 0; i < size; i++, vec_kvaddr += head_size) {
 
-		if (vec[i] == 0)
-			continue;
+		if (head_size == SIZE(list_head)) {
+			if (vec[i*2] == vec_kvaddr)
+				continue;
+		} else {
+			if (vec[i] == 0)
+				continue;
+		}
 
 		BZERO(ld, sizeof(struct list_data));
-		ld->start = vec[i];
+		ld->start = (head_size == SIZE(list_head)) ? vec[i*2] : vec[i];
 		ld->list_head_offset = OFFSET(timer_list_entry);
 		ld->end = vec_kvaddr;
 		ld->flags = RETURN_ON_LIST_ERROR;