Skip to contentSkip to conversation

makedumpfile -g with recent kernels

DISCUSSION Atsushi Kumagai 3 participants 11 messages Aug 2, 2012 – Aug 14, 2012 3 messages not in the archive

Subsystems (2)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

Hello Stefan,

Quoted 11 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

Quoted 3 lines

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Thank you for your nice work!

I think your idea is basically good, however your patch can't take care of
the member of union (e.g. page.lru in kernel 3.2).
Because the member of union hasn't DW_AT_data_member_location and dwarf_info.member_offset isn't be initialized. Therefore, adjust_member_offset() doesn't work for the member of union.

  static void
  adjust_member_offset(Dwarf_Die *die)
  {
          long offset;
          if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)     // this comparison is always true
                  return;
          if (!get_data_member_location(die, &offset))
                  return;
          dwarf_info.member_offset += offset;

}

At least, the change below works fine without regression.

dwarf_info.c +3 -1
index 583df53..03e4c90 100644
@@ -520,7 +520,9 @@ search_member(Dwarf_Die *die)
                        /*
                         * Get the member offset.
                         */
-                       if (!get_data_member_location(walker, &offset))
+                       if (dwarf_tag(die) == DW_TAG_union_type)
+                               offset = 0;
+                       else if (!get_data_member_location(walker, &offset))
                                continue;
                        dwarf_info.member_offset = offset;
                        return TRUE;

Unless you have better way to fix this issue, I'll merge your patch into the next version with the change above.

By the way, this fix enable us also to get the offset of page._mapcount and page.private, it's very helpful for the new method of free page filtering.

http://lists.infradead.org/pipermail/kexec/2012-June/006441.html

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#2 lore raw

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 14:12:51 +0900

Quoted 16 lines

Hello Stefan,

Quoted 11 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

Quoted 6 lines
Quoted 3 lines

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Thank you for your nice work!

Hello Kumagai-san,

I want to see a whole part of Stefan's patch. Could you post it on the ml?

Thanks.
HATAYAMA, Daisuke

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#3 lore raw

Hello HATAYAMA-san,

Quoted 24 lines · On Thu, 02 Aug 2012 14:47:14 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 14:12:51 +0900

Quoted 20 lines

Hello Stefan,

Quoted 14 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Quoted 7 lines
Quoted 2 lines

Thank you for your nice work!

Hello Kumagai-san,

I want to see a whole part of Stefan's patch. Could you post it on the ml?

This is the Stefan's patch.

Thanks
Atsushi Kumagai

---
From cde00fffeddddd1fcffd3085ded0947fdcd159ef Mon Sep 17 00:00:00 2001
From: Stefan Bader <[email protected]>
Date: Thu, 5 Jul 2012 18:03:53 +0200
Subject: [PATCH] Generic search into anonymous members in search_member()

There was a special case to find page.mapping in case it would be inside an anonymous union.struct. But recent kernel versions also moved page._count into the depths of some unnamed elements. Naturally not the same as page.mapping.
So this tries to approach the problem by implementing a generic method of descending into anonymous sub-members. If this finds a member and it is the member offset that is the target of the search, that offset has to be adjusted on the way back out.

---
 dwarf_info.c   |  117 ++++++++++++++++++--------------------------------------
 dwarf_info.h   |    1 -
 makedumpfile.c |    8 ----
 makedumpfile.h |    6 ---
 4 files changed, 38 insertions(+), 94 deletions(-)
dwarf_info.c +38 -79
index 1429858..583df53 100644
@@ -64,7 +64,6 @@ is_search_structure(int cmd)
 	if ((cmd == DWARF_INFO_GET_STRUCT_SIZE)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET)
 	    || (cmd == DWARF_INFO_GET_MEMBER_TYPE)
-	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_ARRAY_LENGTH))
 		return TRUE;
@@ -447,75 +446,40 @@ get_dwarf_base_type(Dwarf_Die *die)
 	return TRUE;
 }
 
-/*
- * Function for searching struct page.union.struct.mapping.
- */
 static int
-__search_mapping(Dwarf_Die *die, long *offset)
+is_anonymous_container(Dwarf_Die *die)
 {
-	int tag;
-	const char *name;
-	Dwarf_Die child, *walker;
-
-	if (dwarf_child(die, &child) != 0)
+	if (dwarf_diename(die))
 		return FALSE;
-
-	walker = &child;
-	do {
-		tag  = dwarf_tag(walker);
-		name = dwarf_diename(walker);
-
-		if (tag != DW_TAG_member)
-			continue;
-		if ((!name) || strcmp(name, dwarf_info.member_name))
-			continue;
-		if (!get_data_member_location(walker, offset))
-			continue;
+	if (dwarf_tag(die) == DW_TAG_union_type)
+		return TRUE;
+	if (dwarf_tag(die) == DW_TAG_structure_type)
 		return TRUE;
-
-	} while (!dwarf_siblingof(walker, walker));
-
 	return FALSE;
 }
 
-/*
- * Function for searching struct page.union.struct.
- */
-static int
-search_mapping(Dwarf_Die *die, long *offset)
+static void
+adjust_member_offset(Dwarf_Die *die)
 {
-	Dwarf_Die child, *walker;
-	Dwarf_Die die_struct;
-
-	if (dwarf_child(die, &child) != 0)
-		return FALSE;
+	long offset;
 
-	walker = &child;
-
-	do {
-		if (dwarf_tag(walker) != DW_TAG_member)
-			continue;
-		if (!get_die_type(walker, &die_struct))
-			continue;
-		if (dwarf_tag(&die_struct) != DW_TAG_structure_type)
-			continue;
-		if (__search_mapping(&die_struct, offset))
-			return TRUE;
-	} while (!dwarf_siblingof(walker, walker));
-
-	return FALSE;
+	if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)
+		return;
+	if (!get_data_member_location(die, &offset))
+		return;
+	dwarf_info.member_offset += offset;
 }
 
-static void
+static int
 search_member(Dwarf_Die *die)
 {
 	int tag;
-	long offset, offset_union;
+	long offset;
 	const char *name;
-	Dwarf_Die child, *walker, die_union;
+	Dwarf_Die child, *walker, die_type;
 
 	if (dwarf_child(die, &child) != 0)
-		return;
+		return FALSE;
 
 	walker = &child;
 
@@ -526,6 +490,20 @@ search_member(Dwarf_Die *die)
 		if (tag != DW_TAG_member)
 			continue;
 
+		/*
+		 * Descend into anonymous members and search for member
+		 * there.
+		 */
+		if (!name) {
+			if (!get_die_type(walker, &die_type))
+				continue;
+			if (is_anonymous_container(&die_type))
+				if (search_member(&die_type)) {
+					adjust_member_offset(walker);
+					return TRUE;
+				}
+		}
+
 		switch (dwarf_info.cmd) {
 		case DWARF_INFO_GET_MEMBER_TYPE:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
@@ -535,7 +513,7 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_dwarf_base_type(walker))
 				continue;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
@@ -545,29 +523,11 @@ search_member(Dwarf_Die *die)
 			if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
-		case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
-			if (!get_die_type(walker, &die_union))
-				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
-				continue;
-			/*
-			 * Search page.mapping in union.
-			 */
-			if (!search_mapping(&die_union, &offset_union))
-				continue;
-
-			/*
-			 * Get the member offset.
-			 */
-			if (!get_data_member_location(walker, &offset))
- 				continue;
-			dwarf_info.member_offset = offset + offset_union;
- 			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
-			if (!get_die_type(walker, &die_union))
+			if (!get_die_type(walker, &die_type))
 				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
+			if (dwarf_tag(&die_type) != DW_TAG_union_type)
 				continue;
 			/*
 			 * Get the member offset.
@@ -575,7 +535,7 @@ search_member(Dwarf_Die *die)
 			if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
@@ -584,14 +544,14 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_data_array_length(walker))
 				continue;
-			return;
+			return TRUE;
 		}
 	} while (!dwarf_siblingof(walker, walker));
 
 	/*
 	 * Return even if not found.
 	 */
-	return;
+	return FALSE;
 }
 
 static void
@@ -636,7 +596,6 @@ search_structure(Dwarf_Die *die, int *found)
 		break;
 	case DWARF_INFO_GET_MEMBER_TYPE:
 	case DWARF_INFO_GET_MEMBER_OFFSET:
-	case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
 	case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
 	case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 		search_member(die);
dwarf_info.h +0 -1
index 1e07484..8d0084d 100644
@@ -37,7 +37,6 @@
 enum {
 	DWARF_INFO_GET_STRUCT_SIZE,
 	DWARF_INFO_GET_MEMBER_OFFSET,
-	DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION,
 	DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION,
 	DWARF_INFO_GET_MEMBER_ARRAY_LENGTH,
 	DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH,
makedumpfile.c +0 -8
index d024e95..d32ce55 100644
@@ -874,17 +874,9 @@ get_structure_info(void)
 	SIZE_INIT(page, "page");
 	OFFSET_INIT(page.flags, "page", "flags");
 	OFFSET_INIT(page._count, "page", "_count");
-
 	OFFSET_INIT(page.mapping, "page", "mapping");
 ---
 	/*
-	 * On linux-2.6.16 or later, page.mapping is defined
-	 * in anonymous union.
-	 */
-	if (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE)
-		OFFSET_IN_UNION_INIT(page.mapping, "page", "mapping");
-
-	/*
 	 * Some vmlinux(s) don't have debugging information about
 	 * page.mapping. Then, makedumpfile assumes that there is
 	 * "mapping" next to "private(unsigned long)" in the first
makedumpfile.h +0 -6
index 6f5489d..4bf502f 100644
@@ -239,12 +239,6 @@ do { \
 	     == FAILED_DWARFINFO) \
 		return FALSE; \
 } while (0)
-#define OFFSET_IN_UNION_INIT(X, Y, Z) \
-do { \
-	if ((OFFSET(X) = get_member_offset(Y, Z, DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)) \
-	     == FAILED_DWARFINFO) \
-		return FALSE; \
-} while (0)
 #define SYMBOL_ARRAY_LENGTH_INIT(X, Y) \
 do { \
 	if ((ARRAY_LENGTH(X) = get_array_length(Y, NULL, DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH)) == FAILED_DWARFINFO) \
Signature · 6 lines
1.7.9.5

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#4 lore raw

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 15:04:29 +0900

Quoted 32 lines

Hello HATAYAMA-san,

Quoted 27 lines · On Thu, 02 Aug 2012 14:47:14 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 14:12:51 +0900

Quoted 22 lines

Hello Stefan,

Quoted 11 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

Quoted 3 lines

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Thank you for your nice work!

Quoted 7 lines
Quoted 4 lines

Hello Kumagai-san,

I want to see a whole part of Stefan's patch. Could you post it on the ml?

This is the Stefan's patch.

Thanks, and this patch helps a lot.

BTW, I think we can get rid of DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION path, too.

Thanks.
HATAYAMA, Daisuke

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#5 lore raw

Hello HATAYAMA-san,

Quoted 44 lines · On Thu, 02 Aug 2012 17:23:05 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 15:04:29 +0900

Quoted 32 lines

Hello HATAYAMA-san,

Quoted 27 lines · On Thu, 02 Aug 2012 14:47:14 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 14:12:51 +0900

Quoted 22 lines

Hello Stefan,

Quoted 11 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

Quoted 3 lines

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Thank you for your nice work!

Quoted 7 lines
Quoted 4 lines

Hello Kumagai-san,

I want to see a whole part of Stefan's patch. Could you post it on the ml?

This is the Stefan's patch.

Quoted 7 lines

Thanks, and this patch helps a lot.

BTW, I think we can get rid of DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION path, too.

Thanks.
HATAYAMA, Daisuke

At first, I thought so. But DWARF_INFO_GET_MEMBER_OFFSET doesn't work for kernel 2.6.16 and 2.6.17 even after applying Stefan's patch. Additionally, I couldn't find the Die of page.mapping with dwarfdump in that case.
I don't know why the Die isn't included in some vmlinuxs, anyway, it seems that the comment below is true.

832 /*
833 * Some vmlinux(s) don't have debugging information about
834 * page.mapping. Then, makedumpfile assumes that there is
835 * "mapping" next to "private(unsigned long)" in the first
836 * union.
837 */
838 if (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE) {
839 OFFSET(page.mapping) = get_member_offset("page", NULL,
840 DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION);

So DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION is still necessary for some kernels.

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#6 lore raw

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Tue, 7 Aug 2012 15:24:09 +0900

Quoted 74 lines

Hello HATAYAMA-san,

Quoted 44 lines · On Thu, 02 Aug 2012 17:23:05 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 15:04:29 +0900

Quoted 32 lines

Hello HATAYAMA-san,

Quoted 27 lines · On Thu, 02 Aug 2012 14:47:14 +0900 (JST) HATAYAMA Daisuke…

From: Atsushi Kumagai <[email protected]>
Subject: Re: makedumpfile -g with recent kernels
Date: Thu, 2 Aug 2012 14:12:51 +0900

Quoted 22 lines

Hello Stefan,

Quoted 11 lines · On Mon, 09 Jul 2012 11:17:13 +0200 Stefan Bader <[email protected]>…

Hi,

I am not sure whether this really is the preferred way as I heard the required info now is in vmcore and vmcoreinfo would not be needed anymore. But just to have it produce some output I noticed that it trips again over some member of struct page that moved into some anonymous structure/union combo. There was some code that was quite specific for the page.mapping case (which now seems to be outside again). I changed the code to be more generic. It did fix my _count problem and should also handle the mapping case (though I could not test). So maybe this would be worth adding to the upstream code.

Quoted 3 lines

-Stefan

Please include me in cc's as I am not subscribed to this ml.

Thank you for your nice work!

Quoted 7 lines
Quoted 4 lines

Hello Kumagai-san,

I want to see a whole part of Stefan's patch. Could you post it on the ml?

This is the Stefan's patch.

Quoted 7 lines

Thanks, and this patch helps a lot.

BTW, I think we can get rid of DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION path, too.

Thanks.
HATAYAMA, Daisuke

At first, I thought so. But DWARF_INFO_GET_MEMBER_OFFSET doesn't work for kernel 2.6.16 and 2.6.17 even after applying Stefan's patch. Additionally, I couldn't find the Die of page.mapping with dwarfdump in that case.
I don't know why the Die isn't included in some vmlinuxs, anyway, it seems that the comment below is true.

832 /*
833 * Some vmlinux(s) don't have debugging information about
834 * page.mapping. Then, makedumpfile assumes that there is
835 * "mapping" next to "private(unsigned long)" in the first
836 * union.
837 */
838 if (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE) {
839 OFFSET(page.mapping) = get_member_offset("page", NULL,
840 DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION);

Quoted 2 lines

So DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION is still necessary for some kernels.

Thanks for your explanation. I understand it. I have similar experience where pt_regs sturcture information is missing for some kernel debuginfo files.

Thanks.
HATAYAMA, Daisuke

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

A message that is not in the archive (sent off-list or not yet received): [email protected]

#8 lore raw

Hello Stefan,

Quoted 15 lines · On Thu, 02 Aug 2012 10:23:13 +0200 Stefan Bader <[email protected]>…
Quoted 15 lines
  static void
  adjust_member_offset(Dwarf_Die *die)
  {
          long offset;
          if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)     // this comparison is always true
                  return;
          if (!get_data_member_location(die, &offset))
                  return;
          dwarf_info.member_offset += offset;

}

At least, the change below works fine without regression.

Quoted 14 lines

dwarf_info.c search_member(Dwarf_Die *die) · line 523

Quoted 10 lines
dwarf_info.c +1 -1
index 583df53..03e4c90 100644
@@ -520,7 +520,9 @@ search_member(Dwarf_Die *die)
                        /*
                         * Get the member offset.
                         */
-                       if (!get_data_member_location(walker, &offset))
+                       if (dwarf_tag(die) == DW_TAG_union_type)

Hm, should that not be die_type to check what the walker is on? And in that case it seems that check was made just before... So maybe it would be ok to assume 0 as the offset when getting here...?

As you said, the walker will be a member of union or struct when reaching here, because is_anonymous_container() already checked the walker.

However, get_data_member_location() must succeed if the walker is a member of struct while it doesn't succeed if the walker is a member of union.
That's why I added the code to check whether the walker is a member of union or not.

Thanks
Atsushi Kumagai

Quoted 13 lines
Quoted 13 lines
dwarf_info.c +2 -0
+                               offset = 0;
+                       else if (!get_data_member_location(walker, &offset))
                                continue;
                        dwarf_info.member_offset = offset;
                        return TRUE;

Unless you have better way to fix this issue, I'll merge your patch into the next version with the change above.

By the way, this fix enable us also to get the offset of page._mapcount and page.private, it's very helpful for the new method of free page filtering.

Quoted 8 lines
Quoted 6 lines

http://lists.infradead.org/pipermail/kexec/2012-June/006441.html

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#9 lore raw
Quoted 35 lines · Atsushi Kumagai

Hello Stefan,

Quoted 15 lines · On Thu, 02 Aug 2012 10:23:13 +0200 Stefan Bader <[email protected]>…
Quoted 15 lines
  static void
  adjust_member_offset(Dwarf_Die *die)
  {
          long offset;
          if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)     // this comparison is always true
                  return;
          if (!get_data_member_location(die, &offset))
                  return;
          dwarf_info.member_offset += offset;

}

At least, the change below works fine without regression.

Quoted 14 lines

dwarf_info.c search_member(Dwarf_Die *die) · line 523

Quoted 10 lines
dwarf_info.c +1 -1
index 583df53..03e4c90 100644
@@ -520,7 +520,9 @@ search_member(Dwarf_Die *die)
                        /*
                         * Get the member offset.
                         */
-                       if (!get_data_member_location(walker, &offset))
+                       if (dwarf_tag(die) == DW_TAG_union_type)

Hm, should that not be die_type to check what the walker is on? And in that case it seems that check was made just before... So maybe it would be ok to assume 0 as the offset when getting here...?

Quoted 6 lines

As you said, the walker will be a member of union or struct when reaching here, because is_anonymous_container() already checked the walker.

However, get_data_member_location() must succeed if the walker is a member of struct while it doesn't succeed if the walker is a member of union.
That's why I added the code to check whether the walker is a member of union or not.

Right, I was just wondering whether that would allow to simplify even more. Like this:

       case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
                if (!get_die_type(walker, &die_type))
                        continue;
                if (dwarf_tag(&die_type) != DW_TAG_union_type)
                        continue;

                /*
                 * At this point it is clear that this is a union.
                 * Though unions have no offset elements (the offset
                 * is always 0. So get_data_member_location would fail.
                 */
                 dwarf_info.member_offset = 0;
                 return TRUE;
Quoted 26 lines

Thanks
Atsushi Kumagai

Quoted 21 lines
Quoted 19 lines
dwarf_info.c +2 -0
+                               offset = 0;
+                       else if (!get_data_member_location(walker, &offset))
                                continue;
                        dwarf_info.member_offset = offset;
                        return TRUE;

Unless you have better way to fix this issue, I'll merge your patch into the next version with the change above.

By the way, this fix enable us also to get the offset of page._mapcount and page.private, it's very helpful for the new method of free page filtering.

http://lists.infradead.org/pipermail/kexec/2012-June/006441.html

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

#10 lore raw

Hello Stefan,

Quoted 39 lines · On Mon, 06 Aug 2012 09:39:53 +0200 Stefan Bader <[email protected]>…
Quoted 38 lines · Atsushi Kumagai

Hello Stefan,

Quoted 15 lines · On Thu, 02 Aug 2012 10:23:13 +0200 Stefan Bader <[email protected]>…
Quoted 15 lines
  static void
  adjust_member_offset(Dwarf_Die *die)
  {
          long offset;
          if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)     // this comparison is always true
                  return;
          if (!get_data_member_location(die, &offset))
                  return;
          dwarf_info.member_offset += offset;

}

At least, the change below works fine without regression.

Quoted 14 lines

dwarf_info.c search_member(Dwarf_Die *die) · line 523

Quoted 10 lines
dwarf_info.c +1 -1
index 583df53..03e4c90 100644
@@ -520,7 +520,9 @@ search_member(Dwarf_Die *die)
                        /*
                         * Get the member offset.
                         */
-                       if (!get_data_member_location(walker, &offset))
+                       if (dwarf_tag(die) == DW_TAG_union_type)

Hm, should that not be die_type to check what the walker is on? And in that case it seems that check was made just before... So maybe it would be ok to assume 0 as the offset when getting here...?

As you said, the walker will be a member of union or struct when reaching here, because is_anonymous_container() already checked the walker.

Quoted 6 lines
Quoted 3 lines

However, get_data_member_location() must succeed if the walker is a member of struct while it doesn't succeed if the walker is a member of union.
That's why I added the code to check whether the walker is a member of union or not.

Right, I was just wondering whether that would allow to simplify even more. Like this:

It seems we misunderstood each other, I talked about DWARF_INFO_GET_MEMBER_OFFSET:

         case DWARF_INFO_GET_MEMBER_OFFSET:
                 if ((!name) || strcmp(name, dwarf_info.member_name))
                         continue;
                 /*
                  * Get the member offset.
                  */
                 if (dwarf_tag(die) == DW_TAG_union_type)
                         offset = 0;
                 else if (!get_data_member_location(walker, &offset))
                         continue;
                 dwarf_info.member_offset = offset;
                 return TRUE;

And about your code:

Quoted 6 lines
       case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
                if (!get_die_type(walker, &die_type))
                        continue;
                if (dwarf_tag(&die_type) != DW_TAG_union_type)
                        continue;
Quoted 7 lines
                /*
                 * At this point it is clear that this is a union.
                 * Though unions have no offset elements (the offset
                 * is always 0. So get_data_member_location would fail.
                 */
                 dwarf_info.member_offset = 0;
                 return TRUE;

It's wrong that unions have no offset elements. Correctly, members of union have no offset elements.

So, I'll fix it similarly to DWARF_INFO_GET_MEMBER_OFFSET:

        case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
                if (!get_die_type(walker, &die_type))
                        continue;
                if (dwarf_tag(&die_type) != DW_TAG_union_type)
                        continue;
                /*
                 * Get the member offset.
                 */
                 if (dwarf_tag(die) == DW_TAG_union_type)
                         offset = 0;
                 else if (!get_data_member_location(walker, &offset))
                         continue;
                 dwarf_info.member_offset = offset;
                 return TRUE;

Thanks
Atsushi Kumagai

Quoted 15 lines
Quoted 15 lines

Thanks
Atsushi Kumagai

Quoted 10 lines
Quoted 10 lines
dwarf_info.c +2 -0
+                               offset = 0;
+                       else if (!get_data_member_location(walker, &offset))
                                continue;
                        dwarf_info.member_offset = offset;
                        return TRUE;

Unless you have better way to fix this issue, I'll merge your patch into the next version with the change above.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

By the way, this fix enable us also to get the offset of page._mapcount and page.private, it's very helpful for the new method of free page filtering.

http://lists.infradead.org/pipermail/kexec/2012-June/006441.html

Thanks
Atsushi Kumagai

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

A message that is not in the archive (sent off-list or not yet received): [email protected]

#12 lore raw

Hello Stefan,

Quoted 33 lines · On Tue, 07 Aug 2012 09:50:49 +0200 Stefan Bader <[email protected]>…
Quoted 30 lines
         case DWARF_INFO_GET_MEMBER_OFFSET:
                 if ((!name) || strcmp(name, dwarf_info.member_name))
                         continue;
                 /*
                  * Get the member offset.
                  */
                 if (dwarf_tag(die) == DW_TAG_union_type)
                         offset = 0;
                 else if (!get_data_member_location(walker, &offset))
                         continue;
                 dwarf_info.member_offset = offset;
                 return TRUE;

And about your code:

Quoted 6 lines
       case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
                if (!get_die_type(walker, &die_type))
                        continue;
                if (dwarf_tag(&die_type) != DW_TAG_union_type)
                        continue;
Quoted 7 lines
                /*
                 * At this point it is clear that this is a union.
                 * Though unions have no offset elements (the offset
                 * is always 0. So get_data_member_location would fail.
                 */
                 dwarf_info.member_offset = 0;
                 return TRUE;
Quoted 2 lines

It's wrong that unions have no offset elements. Correctly, members of union have no offset elements.

Quoted 7 lines

That code was just based on the (incorrect) assumption that we talk about *_OFFSET_1ST_UNION and thinking those were the dies that had no offset tags. But the members having no offset makes much more sense. But then (without looking at dwarf output), if it is only the members of unions that need the change (and now I understand why it is checking die and not die_type), the first union should always have an offset and that call would only descent into structures while looking for the first union and never go past a union.

Did you point out the case like the example below ? (names of unions are only for explanation.)

Example:

	struct EXAMPLE {                  // top layer
		int A;
		union ONE {               // the target of *_OFFSET_1ST_UNION
			int B;
			union TWO {       // but, my code reaches here
				int C;
			};
		};
	};

Certainly, my change for *_OFFSET_1ST_UNION is wrong.
I changed is_anonymous_container() and attach the fixed patch to this mail. I'll merge it into the next version unless you have any comment.

Thanks
Atsushi Kumagai

---
 dwarf_info.c   |  122 +++++++++++++++++++-------------------------------------
 dwarf_info.h   |    1 -
 makedumpfile.c |    8 ----
 makedumpfile.h |    6 ---
 4 files changed, 42 insertions(+), 95 deletions(-)
dwarf_info.c +42 -80
index 1429858..fb11e49 100644
@@ -64,7 +64,6 @@ is_search_structure(int cmd)
 	if ((cmd == DWARF_INFO_GET_STRUCT_SIZE)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET)
 	    || (cmd == DWARF_INFO_GET_MEMBER_TYPE)
-	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_ARRAY_LENGTH))
 		return TRUE;
@@ -447,75 +446,41 @@ get_dwarf_base_type(Dwarf_Die *die)
 	return TRUE;
 }
 
-/*
- * Function for searching struct page.union.struct.mapping.
- */
 static int
-__search_mapping(Dwarf_Die *die, long *offset)
+is_anonymous_container(Dwarf_Die *die)
 {
-	int tag;
-	const char *name;
-	Dwarf_Die child, *walker;
-
-	if (dwarf_child(die, &child) != 0)
+	if (dwarf_diename(die))
 		return FALSE;
-
-	walker = &child;
-	do {
-		tag  = dwarf_tag(walker);
-		name = dwarf_diename(walker);
-
-		if (tag != DW_TAG_member)
-			continue;
-		if ((!name) || strcmp(name, dwarf_info.member_name))
-			continue;
-		if (!get_data_member_location(walker, offset))
-			continue;
+	if (dwarf_tag(die) == DW_TAG_structure_type)
+		return TRUE;
+	if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
+	    && dwarf_tag(die) == DW_TAG_union_type)
 		return TRUE;
-
-	} while (!dwarf_siblingof(walker, walker));
-
 	return FALSE;
 }
 
-/*
- * Function for searching struct page.union.struct.
- */
-static int
-search_mapping(Dwarf_Die *die, long *offset)
+static void
+adjust_member_offset(Dwarf_Die *die)
 {
-	Dwarf_Die child, *walker;
-	Dwarf_Die die_struct;
-
-	if (dwarf_child(die, &child) != 0)
-		return FALSE;
-
-	walker = &child;
-
-	do {
-		if (dwarf_tag(walker) != DW_TAG_member)
-			continue;
-		if (!get_die_type(walker, &die_struct))
-			continue;
-		if (dwarf_tag(&die_struct) != DW_TAG_structure_type)
-			continue;
-		if (__search_mapping(&die_struct, offset))
-			return TRUE;
-	} while (!dwarf_siblingof(walker, walker));
+	long offset;
 
-	return FALSE;
+	if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)
+		return;
+	if (!get_data_member_location(die, &offset))
+		return;
+	dwarf_info.member_offset += offset;
 }
 
-static void
+static int
 search_member(Dwarf_Die *die)
 {
 	int tag;
-	long offset, offset_union;
+	long offset;
 	const char *name;
-	Dwarf_Die child, *walker, die_union;
+	Dwarf_Die child, *walker, die_type;
 
 	if (dwarf_child(die, &child) != 0)
-		return;
+		return FALSE;
 
 	walker = &child;
 
@@ -526,6 +491,20 @@ search_member(Dwarf_Die *die)
 		if (tag != DW_TAG_member)
 			continue;
 
+		/*
+		 * Descend into anonymous members and search for member
+		 * there.
+		 */
+		if (!name) {
+			if (!get_die_type(walker, &die_type))
+				continue;
+			if (is_anonymous_container(&die_type))
+				if (search_member(&die_type)) {
+					adjust_member_offset(walker);
+					return TRUE;
+				}
+		}
+
 		switch (dwarf_info.cmd) {
 		case DWARF_INFO_GET_MEMBER_TYPE:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
@@ -535,39 +514,23 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_dwarf_base_type(walker))
 				continue;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
 			/*
 			 * Get the member offset.
 			 */
-			if (!get_data_member_location(walker, &offset))
+			if (dwarf_tag(die) == DW_TAG_union_type)
+				offset = 0;
+			else if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
-		case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
-			if (!get_die_type(walker, &die_union))
-				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
-				continue;
-			/*
-			 * Search page.mapping in union.
-			 */
-			if (!search_mapping(&die_union, &offset_union))
-				continue;
-
-			/*
-			 * Get the member offset.
-			 */
-			if (!get_data_member_location(walker, &offset))
- 				continue;
-			dwarf_info.member_offset = offset + offset_union;
- 			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
-			if (!get_die_type(walker, &die_union))
+			if (!get_die_type(walker, &die_type))
 				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
+			if (dwarf_tag(&die_type) != DW_TAG_union_type)
 				continue;
 			/*
 			 * Get the member offset.
@@ -575,7 +538,7 @@ search_member(Dwarf_Die *die)
 			if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
@@ -584,14 +547,14 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_data_array_length(walker))
 				continue;
-			return;
+			return TRUE;
 		}
 	} while (!dwarf_siblingof(walker, walker));
 
 	/*
 	 * Return even if not found.
 	 */
-	return;
+	return FALSE;
 }
 
 static void
@@ -636,7 +599,6 @@ search_structure(Dwarf_Die *die, int *found)
 		break;
 	case DWARF_INFO_GET_MEMBER_TYPE:
 	case DWARF_INFO_GET_MEMBER_OFFSET:
-	case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
 	case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
 	case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 		search_member(die);
dwarf_info.h +0 -1
index 1e07484..8d0084d 100644
@@ -37,7 +37,6 @@
 enum {
 	DWARF_INFO_GET_STRUCT_SIZE,
 	DWARF_INFO_GET_MEMBER_OFFSET,
-	DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION,
 	DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION,
 	DWARF_INFO_GET_MEMBER_ARRAY_LENGTH,
 	DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH,
makedumpfile.c +0 -8
index d024e95..d32ce55 100644
@@ -874,17 +874,9 @@ get_structure_info(void)
 	SIZE_INIT(page, "page");
 	OFFSET_INIT(page.flags, "page", "flags");
 	OFFSET_INIT(page._count, "page", "_count");
-
 	OFFSET_INIT(page.mapping, "page", "mapping");
 
 	/*
-	 * On linux-2.6.16 or later, page.mapping is defined
-	 * in anonymous union.
-	 */
-	if (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE)
-		OFFSET_IN_UNION_INIT(page.mapping, "page", "mapping");
-
-	/*
 	 * Some vmlinux(s) don't have debugging information about
 	 * page.mapping. Then, makedumpfile assumes that there is
 	 * "mapping" next to "private(unsigned long)" in the first
makedumpfile.h +0 -6
index 6f5489d..4bf502f 100644
@@ -239,12 +239,6 @@ do { \
 	     == FAILED_DWARFINFO) \
 		return FALSE; \
 } while (0)
-#define OFFSET_IN_UNION_INIT(X, Y, Z) \
-do { \
-	if ((OFFSET(X) = get_member_offset(Y, Z, DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)) \
-	     == FAILED_DWARFINFO) \
-		return FALSE; \
-} while (0)
 #define SYMBOL_ARRAY_LENGTH_INIT(X, Y) \
 do { \
 	if ((ARRAY_LENGTH(X) = get_array_length(Y, NULL, DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH)) == FAILED_DWARFINFO) \
Signature · 6 lines
1.7.9.2

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
#13 lore raw
Quoted 61 lines · Atsushi Kumagai

Hello Stefan,

Quoted 33 lines · On Tue, 07 Aug 2012 09:50:49 +0200 Stefan Bader <[email protected]>…
Quoted 30 lines
         case DWARF_INFO_GET_MEMBER_OFFSET:
                 if ((!name) || strcmp(name, dwarf_info.member_name))
                         continue;
                 /*
                  * Get the member offset.
                  */
                 if (dwarf_tag(die) == DW_TAG_union_type)
                         offset = 0;
                 else if (!get_data_member_location(walker, &offset))
                         continue;
                 dwarf_info.member_offset = offset;
                 return TRUE;

And about your code:

Quoted 6 lines
       case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
                if (!get_die_type(walker, &die_type))
                        continue;
                if (dwarf_tag(&die_type) != DW_TAG_union_type)
                        continue;
Quoted 7 lines
                /*
                 * At this point it is clear that this is a union.
                 * Though unions have no offset elements (the offset
                 * is always 0. So get_data_member_location would fail.
                 */
                 dwarf_info.member_offset = 0;
                 return TRUE;
Quoted 2 lines

It's wrong that unions have no offset elements. Correctly, members of union have no offset elements.

Quoted 7 lines

That code was just based on the (incorrect) assumption that we talk about *_OFFSET_1ST_UNION and thinking those were the dies that had no offset tags. But the members having no offset makes much more sense. But then (without looking at dwarf output), if it is only the members of unions that need the change (and now I understand why it is checking die and not die_type), the first union should always have an offset and that call would only descent into structures while looking for the first union and never go past a union.

Did you point out the case like the example below ? (names of unions are only for explanation.)

Example:

	struct EXAMPLE {                  // top layer
		int A;
		union ONE {               // the target of *_OFFSET_1ST_UNION
			int B;
			union TWO {       // but, my code reaches here
				int C;
			};
		};
	};
Quoted 3 lines

Certainly, my change for *_OFFSET_1ST_UNION is wrong.
I changed is_anonymous_container() and attach the fixed patch to this mail. I'll merge it into the next version unless you have any comment.

Yes, and that was actually already wrong with my initial patch. Damn these little details... So now, when looking for the first union, the recursion stops at the first one. Sounds good.

I think this looks good now... hopefully... :) Thanks.

-Stefan

Quoted 262 lines

Thanks
Atsushi Kumagai

---
 dwarf_info.c   |  122 +++++++++++++++++++-------------------------------------
 dwarf_info.h   |    1 -
 makedumpfile.c |    8 ----
 makedumpfile.h |    6 ---
 4 files changed, 42 insertions(+), 95 deletions(-)
dwarf_info.c +42 -80
index 1429858..fb11e49 100644
@@ -64,7 +64,6 @@ is_search_structure(int cmd)
 	if ((cmd == DWARF_INFO_GET_STRUCT_SIZE)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET)
 	    || (cmd == DWARF_INFO_GET_MEMBER_TYPE)
-	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION)
 	    || (cmd == DWARF_INFO_GET_MEMBER_ARRAY_LENGTH))
 		return TRUE;
@@ -447,75 +446,41 @@ get_dwarf_base_type(Dwarf_Die *die)
 	return TRUE;
 }
 
-/*
- * Function for searching struct page.union.struct.mapping.
- */
 static int
-__search_mapping(Dwarf_Die *die, long *offset)
+is_anonymous_container(Dwarf_Die *die)
 {
-	int tag;
-	const char *name;
-	Dwarf_Die child, *walker;
-
-	if (dwarf_child(die, &child) != 0)
+	if (dwarf_diename(die))
 		return FALSE;
-
-	walker = &child;
-	do {
-		tag  = dwarf_tag(walker);
-		name = dwarf_diename(walker);
-
-		if (tag != DW_TAG_member)
-			continue;
-		if ((!name) || strcmp(name, dwarf_info.member_name))
-			continue;
-		if (!get_data_member_location(walker, offset))
-			continue;
+	if (dwarf_tag(die) == DW_TAG_structure_type)
+		return TRUE;
+	if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
+	    && dwarf_tag(die) == DW_TAG_union_type)
 		return TRUE;
-
-	} while (!dwarf_siblingof(walker, walker));
-
 	return FALSE;
 }
 
-/*
- * Function for searching struct page.union.struct.
- */
-static int
-search_mapping(Dwarf_Die *die, long *offset)
+static void
+adjust_member_offset(Dwarf_Die *die)
 {
-	Dwarf_Die child, *walker;
-	Dwarf_Die die_struct;
-
-	if (dwarf_child(die, &child) != 0)
-		return FALSE;
-
-	walker = &child;
-
-	do {
-		if (dwarf_tag(walker) != DW_TAG_member)
-			continue;
-		if (!get_die_type(walker, &die_struct))
-			continue;
-		if (dwarf_tag(&die_struct) != DW_TAG_structure_type)
-			continue;
-		if (__search_mapping(&die_struct, offset))
-			return TRUE;
-	} while (!dwarf_siblingof(walker, walker));
+	long offset;
 
-	return FALSE;
+	if (dwarf_info.member_offset == NOT_FOUND_STRUCTURE)
+		return;
+	if (!get_data_member_location(die, &offset))
+		return;
+	dwarf_info.member_offset += offset;
 }
 
-static void
+static int
 search_member(Dwarf_Die *die)
 {
 	int tag;
-	long offset, offset_union;
+	long offset;
 	const char *name;
-	Dwarf_Die child, *walker, die_union;
+	Dwarf_Die child, *walker, die_type;
 
 	if (dwarf_child(die, &child) != 0)
-		return;
+		return FALSE;
 
 	walker = &child;
 
@@ -526,6 +491,20 @@ search_member(Dwarf_Die *die)
 		if (tag != DW_TAG_member)
 			continue;
 
+		/*
+		 * Descend into anonymous members and search for member
+		 * there.
+		 */
+		if (!name) {
+			if (!get_die_type(walker, &die_type))
+				continue;
+			if (is_anonymous_container(&die_type))
+				if (search_member(&die_type)) {
+					adjust_member_offset(walker);
+					return TRUE;
+				}
+		}
+
 		switch (dwarf_info.cmd) {
 		case DWARF_INFO_GET_MEMBER_TYPE:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
@@ -535,39 +514,23 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_dwarf_base_type(walker))
 				continue;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
 			/*
 			 * Get the member offset.
 			 */
-			if (!get_data_member_location(walker, &offset))
+			if (dwarf_tag(die) == DW_TAG_union_type)
+				offset = 0;
+			else if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
-		case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
-			if (!get_die_type(walker, &die_union))
-				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
-				continue;
-			/*
-			 * Search page.mapping in union.
-			 */
-			if (!search_mapping(&die_union, &offset_union))
-				continue;
-
-			/*
-			 * Get the member offset.
-			 */
-			if (!get_data_member_location(walker, &offset))
- 				continue;
-			dwarf_info.member_offset = offset + offset_union;
- 			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
-			if (!get_die_type(walker, &die_union))
+			if (!get_die_type(walker, &die_type))
 				continue;
-			if (dwarf_tag(&die_union) != DW_TAG_union_type)
+			if (dwarf_tag(&die_type) != DW_TAG_union_type)
 				continue;
 			/*
 			 * Get the member offset.
@@ -575,7 +538,7 @@ search_member(Dwarf_Die *die)
 			if (!get_data_member_location(walker, &offset))
 				continue;
 			dwarf_info.member_offset = offset;
-			return;
+			return TRUE;
 		case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 			if ((!name) || strcmp(name, dwarf_info.member_name))
 				continue;
@@ -584,14 +547,14 @@ search_member(Dwarf_Die *die)
 			 */
 			if (!get_data_array_length(walker))
 				continue;
-			return;
+			return TRUE;
 		}
 	} while (!dwarf_siblingof(walker, walker));
 
 	/*
 	 * Return even if not found.
 	 */
-	return;
+	return FALSE;
 }
 
 static void
@@ -636,7 +599,6 @@ search_structure(Dwarf_Die *die, int *found)
 		break;
 	case DWARF_INFO_GET_MEMBER_TYPE:
 	case DWARF_INFO_GET_MEMBER_OFFSET:
-	case DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION:
 	case DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION:
 	case DWARF_INFO_GET_MEMBER_ARRAY_LENGTH:
 		search_member(die);
dwarf_info.h +0 -1
index 1e07484..8d0084d 100644
@@ -37,7 +37,6 @@
 enum {
 	DWARF_INFO_GET_STRUCT_SIZE,
 	DWARF_INFO_GET_MEMBER_OFFSET,
-	DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION,
 	DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION,
 	DWARF_INFO_GET_MEMBER_ARRAY_LENGTH,
 	DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH,
makedumpfile.c +0 -8
index d024e95..d32ce55 100644
@@ -874,17 +874,9 @@ get_structure_info(void)
 	SIZE_INIT(page, "page");
 	OFFSET_INIT(page.flags, "page", "flags");
 	OFFSET_INIT(page._count, "page", "_count");
-
 	OFFSET_INIT(page.mapping, "page", "mapping");
 
 	/*
-	 * On linux-2.6.16 or later, page.mapping is defined
-	 * in anonymous union.
-	 */
-	if (OFFSET(page.mapping) == NOT_FOUND_STRUCTURE)
-		OFFSET_IN_UNION_INIT(page.mapping, "page", "mapping");
-
-	/*
 	 * Some vmlinux(s) don't have debugging information about
 	 * page.mapping. Then, makedumpfile assumes that there is
 	 * "mapping" next to "private(unsigned long)" in the first
makedumpfile.h +0 -0
index 6f5489d..4bf502f 100644
@@ -239,12 +239,6 @@ do { \
 	     == FAILED_DWARFINFO) \
 		return FALSE; \

makedumpfile.h do { \ · line 244

Quoted 10 lines
makedumpfile.h +0 -6
 } while (0)
-#define OFFSET_IN_UNION_INIT(X, Y, Z) \
-do { \
-	if ((OFFSET(X) = get_member_offset(Y, Z, DWARF_INFO_GET_MEMBER_OFFSET_IN_UNION)) \
-	     == FAILED_DWARFINFO) \
-		return FALSE; \
-} while (0)
 #define SYMBOL_ARRAY_LENGTH_INIT(X, Y) \
 do { \
 	if ((ARRAY_LENGTH(X) = get_array_length(Y, NULL, DWARF_INFO_GET_SYMBOL_ARRAY_LENGTH)) == FAILED_DWARFINFO) \

_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec